diff --git a/app/boot_levels.go b/app/boot_levels.go index 701e7d355..e05b8969b 100644 --- a/app/boot_levels.go +++ b/app/boot_levels.go @@ -24,6 +24,7 @@ import ( "github.com/cortezaproject/corteza-server/pkg/dal" "github.com/cortezaproject/corteza-server/pkg/dal/capabilities" "github.com/cortezaproject/corteza-server/pkg/eventbus" + "github.com/cortezaproject/corteza-server/pkg/geolocation" "github.com/cortezaproject/corteza-server/pkg/healthcheck" "github.com/cortezaproject/corteza-server/pkg/http" "github.com/cortezaproject/corteza-server/pkg/id" @@ -300,17 +301,24 @@ func (app *CortezaApp) InitServices(ctx context.Context) (err error) { var primaryDalConnection = types.DalConnection{ // Using id.Next since we dropped "special" ids a while ago. // If needed, use the handle - ID: id.Next(), - Handle: "primary_connection", - DSN: app.Opt.DB.DSN, - Location: "@todo", + ID: id.Next(), + Name: "Primary Connection", + Handle: "primary_connection", + Type: types.DalPrimaryConnectionResourceType, + + Location: &geolocation.Full{ + // @todo get from .env + }, Ownership: "@todo", // @todo - Sensitive: true, + // SensitivityLevel: , + Config: types.ConnectionConfig{ DefaultModelIdent: defaultComposeRecordTable, DefaultAttributeIdent: defaultComposeRecordValueCol, DefaultPartitionFormat: defaultPartitionFormat, + + Connection: dal.NewDSNConnection(app.Opt.DB.DSN), }, Capabilities: types.ConnectionCapabilities{ Supported: capabilities.FullCapabilities(), @@ -326,7 +334,7 @@ func (app *CortezaApp) InitServices(ctx context.Context) (err error) { app.Opt.Environment.IsDevelopment(), // DB_DSN is the default connection with full capabilities - primaryDalConnection.DSN, + primaryDalConnection.Config.Connection, primaryDalConnection.ConnectionDefaults(), primaryDalConnection.ActiveCapabilities()...); err != nil { return err diff --git a/codegen/assets/templates/gocode/store/rdbms/aux_types.go.tpl b/codegen/assets/templates/gocode/store/rdbms/aux_types.go.tpl index 6721e9c6c..e107a534e 100644 --- a/codegen/assets/templates/gocode/store/rdbms/aux_types.go.tpl +++ b/codegen/assets/templates/gocode/store/rdbms/aux_types.go.tpl @@ -5,6 +5,7 @@ package rdbms import ( "time" "github.com/cortezaproject/corteza-server/pkg/expr" + "github.com/cortezaproject/corteza-server/pkg/geolocation" {{- range $path, $alias := .imports }} {{ $alias }} {{ printf "%q" $path }} {{- end }} diff --git a/pkg/dal/driver.go b/pkg/dal/driver.go index d76fe812b..b19ec4d72 100644 --- a/pkg/dal/driver.go +++ b/pkg/dal/driver.go @@ -16,6 +16,11 @@ import ( type ( PKValues map[string]any + ConnectionParams struct { + Type string `json:"type"` + Params map[string]any `json:"params"` + } + Connection interface { // Meta @@ -113,10 +118,28 @@ type ( } ConnectorFn func(ctx context.Context, dsn string, cc ...capabilities.Capability) (Connection, error) + + DriverConnectionParam struct { + Key string `json:"key"` + ValueType string `json:"valueType"` + MultiValue bool `json:"multiValue"` + } + + DriverConnectionConfig struct { + Type string `json:"type"` + Params []DriverConnectionParam `json:"params"` + } + + Driver struct { + Type string `json:"type"` + Connection DriverConnectionConfig `json:"connection"` + Capabilities capabilities.Set `json:"capabilities"` + } ) var ( - registered = make(map[string]ConnectorFn) + registeredConnectors = make(map[string]ConnectorFn) + registeredDrivers = make(map[string]Driver) ) func (pkv PKValues) CountValues() map[string]uint { @@ -136,17 +159,25 @@ func (pkv PKValues) GetValue(key string, _ uint) (any, error) { } } -// Register registers a new connector for the given DSN schema +// RegisterConnector registers a new connector for the given DSN schema // // In case of a duplicate schema the latter overwrites the prior -func Register(fn ConnectorFn, tt ...string) { +func RegisterConnector(fn ConnectorFn, tt ...string) { for _, t := range tt { - registered[t] = fn + registeredConnectors[t] = fn } } +func RegisterDriver(d Driver) { + registeredDrivers[d.Type] = d +} + // connect opens a new StoreConnection for the given CRS -func connect(ctx context.Context, log *zap.Logger, isDevelopment bool, dsn string, capabilities ...capabilities.Capability) (Connection, error) { +func connect(ctx context.Context, log *zap.Logger, isDevelopment bool, cp ConnectionParams, capabilities ...capabilities.Capability) (Connection, error) { + if cp.Type != "corteza::dal:connection:dsn" { + return nil, fmt.Errorf("cannot open connection: only DSN connections supported") + } + dsn := cp.Params["dsn"].(string) if isDevelopment { if strings.Contains(dsn, "{version}") { @@ -165,9 +196,64 @@ func connect(ctx context.Context, log *zap.Logger, isDevelopment bool, dsn strin storeType = "mysql" } - if conn, ok := registered[storeType]; ok { + if conn, ok := registeredConnectors[storeType]; ok { return conn(ctx, dsn, capabilities...) } else { return nil, fmt.Errorf("unknown store type used: %q (check your storage configuration)", storeType) } } + +func NewDSNDriverConnectionConfig() DriverConnectionConfig { + return DriverConnectionConfig{ + Type: "corteza::dal:connection:dsn", + Params: []DriverConnectionParam{{ + Key: "dsn", + ValueType: "string", + }}, + } +} +func NewHTTPDriverConnectionConfig() DriverConnectionConfig { + panic("not implemented NewHTTPDriverConnectionConfig") + return DriverConnectionConfig{ + Type: "corteza::dal:connection:http", + Params: []DriverConnectionParam{{}}, + } +} +func NewFederatedNodeDriverConnectionConfig() DriverConnectionConfig { + panic("not implemented NewFederatedNodeDriverConnectionConfig") + return DriverConnectionConfig{ + Type: "corteza::dal:connection:federated-node", + Params: []DriverConnectionParam{{}}, + } +} + +func NewDSNConnection(dsn string) ConnectionParams { + return ConnectionParams{ + Type: "corteza::dal:connection:dsn", + Params: map[string]any{ + "dsn": dsn, + }, + } +} + +func NewHTTPConnection(url string, headers, query map[string][]string) ConnectionParams { + return ConnectionParams{ + Type: "corteza::dal:connection:http", + Params: map[string]any{ + "url": url, + "headers": headers, + "query": query, + }, + } +} + +func NewFederatedNodeCOnnection(url string, pairToken, authToken string) ConnectionParams { + return ConnectionParams{ + Type: "corteza::dal:connection:federation-node", + Params: map[string]any{ + "baseURL": url, + "pairToken": pairToken, + "authToken": authToken, + }, + } +} diff --git a/pkg/dal/service.go b/pkg/dal/service.go index 04864cb0b..e24b28631 100644 --- a/pkg/dal/service.go +++ b/pkg/dal/service.go @@ -43,7 +43,7 @@ var ( ) // InitGlobalService initializes a fresh DAL where the given primary connection -func InitGlobalService(ctx context.Context, log *zap.Logger, inDev bool, dsn string, dft ConnectionDefaults, capabilities ...capabilities.Capability) (*service, error) { +func InitGlobalService(ctx context.Context, log *zap.Logger, inDev bool, cp ConnectionParams, dft ConnectionDefaults, capabilities ...capabilities.Capability) (*service, error) { if gSvc == nil { gSvc = &service{ connections: make(map[uint64]*connectionWrap), @@ -58,7 +58,7 @@ func InitGlobalService(ctx context.Context, log *zap.Logger, inDev bool, dsn str cw := &connectionWrap{ Defaults: dft, } - cw.connection, err = connect(ctx, log, inDev, dsn, capabilities...) + cw.connection, err = connect(ctx, log, inDev, cp, capabilities...) if err != nil { return nil, err } @@ -80,15 +80,28 @@ func Service() *service { return gSvc } +// // // // // // // // // // // // // // // // // // // // // // // // // +// driver management + +func (svc *service) Drivers() (drivers []Driver) { + for _, d := range registeredDrivers { + drivers = append(drivers, d) + } + + return +} + +// // // // // // // // // // // // // // // // // // // // // // // // // + // // // // // // // // // // // // // // // // // // // // // // // // // // Connection management // AddConnection adds a new connection to the DAL -func (svc *service) AddConnection(ctx context.Context, connectionID uint64, dsn string, dft ConnectionDefaults, capabilities ...capabilities.Capability) (err error) { +func (svc *service) AddConnection(ctx context.Context, connectionID uint64, cp ConnectionParams, dft ConnectionDefaults, capabilities ...capabilities.Capability) (err error) { cw := &connectionWrap{ Defaults: dft, } - cw.connection, err = connect(ctx, svc.logger, svc.inDev, dsn, capabilities...) + cw.connection, err = connect(ctx, svc.logger, svc.inDev, cp, capabilities...) if err != nil { return } @@ -119,12 +132,12 @@ func (svc *service) RemoveConnection(ctx context.Context, connectionID uint64) ( // UpdateConnection updates the given connection // // @todo make this better; for now remove + add -func (svc *service) UpdateConnection(ctx context.Context, connectionID uint64, dsn string, dft ConnectionDefaults, capabilities ...capabilities.Capability) (err error) { +func (svc *service) UpdateConnection(ctx context.Context, connectionID uint64, cp ConnectionParams, dft ConnectionDefaults, capabilities ...capabilities.Capability) (err error) { if err = svc.RemoveConnection(ctx, connectionID); err != nil { return } - return svc.AddConnection(ctx, connectionID, dsn, dft, capabilities...) + return svc.AddConnection(ctx, connectionID, cp, dft, capabilities...) } // ConnectionDefaultreturns the defaults we can use with this connection diff --git a/pkg/envoy/resource/rbac_references_system.gen.go b/pkg/envoy/resource/rbac_references_system.gen.go index f7feb9922..8d33581f3 100644 --- a/pkg/envoy/resource/rbac_references_system.gen.go +++ b/pkg/envoy/resource/rbac_references_system.gen.go @@ -139,3 +139,16 @@ func SystemDalConnectionRbacReferences(dalConnection string) (res *Ref, pp []*Re return } + +// SystemDalSensitivityLevelRbacReferences generates RBAC references +// +// Resources with "envoy: false" are skipped +// +// This function is auto-generated +func SystemDalSensitivityLevelRbacReferences(dalSensitivityLevel string) (res *Ref, pp []*Ref, err error) { + if dalSensitivityLevel != "*" { + res = &Ref{ResourceType: types.DalSensitivityLevelResourceType, Identifiers: MakeIdentifiers(dalSensitivityLevel)} + } + + return +} diff --git a/pkg/envoy/resource/rbac_rules_parse.gen.go b/pkg/envoy/resource/rbac_rules_parse.gen.go index 035c303f5..f30755ae7 100644 --- a/pkg/envoy/resource/rbac_rules_parse.gen.go +++ b/pkg/envoy/resource/rbac_rules_parse.gen.go @@ -137,6 +137,15 @@ func ParseRule(res string) (string, *Ref, []*Ref, error) { ) return resourceType, ref, pp, err + case systemTypes.DalSensitivityLevelResourceType: + if len(path) != 1 { + return "", nil, nil, fmt.Errorf("expecting 1 reference components in path, got %d", len(path)) + } + ref, pp, err := SystemDalSensitivityLevelRbacReferences( + path[0], + ) + return resourceType, ref, pp, err + case composeTypes.ChartResourceType: if len(path) != 2 { return "", nil, nil, fmt.Errorf("expecting 2 reference components in path, got %d", len(path)) diff --git a/pkg/geolocation/geolocation.go b/pkg/geolocation/geolocation.go new file mode 100644 index 000000000..3d1d9c04a --- /dev/null +++ b/pkg/geolocation/geolocation.go @@ -0,0 +1,42 @@ +package geolocation + +import ( + "database/sql/driver" + "encoding/json" +) + +type ( + Geometry struct { + Type string `json:"type"` + Coordinates [2]float64 `json:"coordinates"` + } + + Properties struct { + Name string `json:"name"` + } + + Full struct { + Geometry Geometry `json:"geometry"` + Properties Properties `json:"properties"` + } +) + +func Parse(ss []string) (m *Full, err error) { + if len(ss) == 0 { + return + } + + err = json.Unmarshal([]byte(ss[0]), &m) + return +} + +func (set *Full) Scan(src interface{}) error { + if data, ok := src.([]byte); ok { + return json.Unmarshal(data, set) + } + return nil +} + +func (set Full) Value() (driver.Value, error) { + return json.Marshal(set) +} diff --git a/store/adapters/rdbms/aux_types.gen.go b/store/adapters/rdbms/aux_types.gen.go index da7ef6abf..aa73ea28b 100644 --- a/store/adapters/rdbms/aux_types.gen.go +++ b/store/adapters/rdbms/aux_types.gen.go @@ -14,6 +14,7 @@ import ( discoveryType "github.com/cortezaproject/corteza-server/pkg/discovery/types" "github.com/cortezaproject/corteza-server/pkg/expr" flagType "github.com/cortezaproject/corteza-server/pkg/flag/types" + "github.com/cortezaproject/corteza-server/pkg/geolocation" labelsType "github.com/cortezaproject/corteza-server/pkg/label/types" rbacType "github.com/cortezaproject/corteza-server/pkg/rbac" systemType "github.com/cortezaproject/corteza-server/system/types" @@ -346,20 +347,35 @@ type ( // auxDalConnection is an auxiliary structure used for transporting to/from RDBMS store auxDalConnection struct { - ID uint64 `db:"id"` - Handle string `db:"handle"` - DSN string `db:"dsn"` - Location string `db:"location"` - Ownership string `db:"ownership"` - Sensitive bool `db:"sensitive"` - Config systemType.ConnectionConfig `db:"config"` - Capabilities systemType.ConnectionCapabilities `db:"capabilities"` - CreatedAt time.Time `db:"created_at"` - UpdatedAt *time.Time `db:"updated_at"` - DeletedAt *time.Time `db:"deleted_at"` - CreatedBy uint64 `db:"created_by"` - UpdatedBy uint64 `db:"updated_by"` - DeletedBy uint64 `db:"deleted_by"` + ID uint64 `db:"id"` + Name string `db:"name"` + Handle string `db:"handle"` + Type string `db:"type"` + Location *geolocation.Full `db:"location"` + Ownership string `db:"ownership"` + SensitivityLevel uint64 `db:"sensitivity_level"` + Config systemType.ConnectionConfig `db:"config"` + Capabilities systemType.ConnectionCapabilities `db:"capabilities"` + CreatedAt time.Time `db:"created_at"` + UpdatedAt *time.Time `db:"updated_at"` + DeletedAt *time.Time `db:"deleted_at"` + CreatedBy uint64 `db:"created_by"` + UpdatedBy uint64 `db:"updated_by"` + DeletedBy uint64 `db:"deleted_by"` + } + + // auxDalSensitivityLevel is an auxiliary structure used for transporting to/from RDBMS store + auxDalSensitivityLevel struct { + ID uint64 `db:"id"` + Handle string `db:"handle"` + Level int `db:"level"` + Meta systemType.DalSensitivityLevelMeta `db:"meta"` + CreatedAt time.Time `db:"created_at"` + UpdatedAt *time.Time `db:"updated_at"` + DeletedAt *time.Time `db:"deleted_at"` + CreatedBy uint64 `db:"created_by"` + UpdatedBy uint64 `db:"updated_by"` + DeletedBy uint64 `db:"deleted_by"` } // auxFederationExposedModule is an auxiliary structure used for transporting to/from RDBMS store @@ -1801,11 +1817,12 @@ func (aux *auxCredential) scan(row scanner) error { // This function is auto-generated func (aux *auxDalConnection) encode(res *systemType.DalConnection) (_ error) { aux.ID = res.ID + aux.Name = res.Name aux.Handle = res.Handle - aux.DSN = res.DSN + aux.Type = res.Type aux.Location = res.Location aux.Ownership = res.Ownership - aux.Sensitive = res.Sensitive + aux.SensitivityLevel = res.SensitivityLevel aux.Config = res.Config aux.Capabilities = res.Capabilities aux.CreatedAt = res.CreatedAt @@ -1823,11 +1840,12 @@ func (aux *auxDalConnection) encode(res *systemType.DalConnection) (_ error) { func (aux auxDalConnection) decode() (res *systemType.DalConnection, _ error) { res = new(systemType.DalConnection) res.ID = aux.ID + res.Name = aux.Name res.Handle = aux.Handle - res.DSN = aux.DSN + res.Type = aux.Type res.Location = aux.Location res.Ownership = aux.Ownership - res.Sensitive = aux.Sensitive + res.SensitivityLevel = aux.SensitivityLevel res.Config = aux.Config res.Capabilities = aux.Capabilities res.CreatedAt = aux.CreatedAt @@ -1845,11 +1863,12 @@ func (aux auxDalConnection) decode() (res *systemType.DalConnection, _ error) { func (aux *auxDalConnection) scan(row scanner) error { return row.Scan( &aux.ID, + &aux.Name, &aux.Handle, - &aux.DSN, + &aux.Type, &aux.Location, &aux.Ownership, - &aux.Sensitive, + &aux.SensitivityLevel, &aux.Config, &aux.Capabilities, &aux.CreatedAt, @@ -1861,6 +1880,59 @@ func (aux *auxDalConnection) scan(row scanner) error { ) } +// encodes DalSensitivityLevel to auxDalSensitivityLevel +// +// This function is auto-generated +func (aux *auxDalSensitivityLevel) encode(res *systemType.DalSensitivityLevel) (_ error) { + aux.ID = res.ID + aux.Handle = res.Handle + aux.Level = res.Level + aux.Meta = res.Meta + aux.CreatedAt = res.CreatedAt + aux.UpdatedAt = res.UpdatedAt + aux.DeletedAt = res.DeletedAt + aux.CreatedBy = res.CreatedBy + aux.UpdatedBy = res.UpdatedBy + aux.DeletedBy = res.DeletedBy + return +} + +// decodes DalSensitivityLevel from auxDalSensitivityLevel +// +// This function is auto-generated +func (aux auxDalSensitivityLevel) decode() (res *systemType.DalSensitivityLevel, _ error) { + res = new(systemType.DalSensitivityLevel) + res.ID = aux.ID + res.Handle = aux.Handle + res.Level = aux.Level + res.Meta = aux.Meta + res.CreatedAt = aux.CreatedAt + res.UpdatedAt = aux.UpdatedAt + res.DeletedAt = aux.DeletedAt + res.CreatedBy = aux.CreatedBy + res.UpdatedBy = aux.UpdatedBy + res.DeletedBy = aux.DeletedBy + return +} + +// scans row and fills auxDalSensitivityLevel fields +// +// This function is auto-generated +func (aux *auxDalSensitivityLevel) scan(row scanner) error { + return row.Scan( + &aux.ID, + &aux.Handle, + &aux.Level, + &aux.Meta, + &aux.CreatedAt, + &aux.UpdatedAt, + &aux.DeletedAt, + &aux.CreatedBy, + &aux.UpdatedBy, + &aux.DeletedBy, + ) +} + // encodes FederationExposedModule to auxFederationExposedModule // // This function is auto-generated diff --git a/store/adapters/rdbms/dal/connection.go b/store/adapters/rdbms/dal/connection.go index bfbabaed3..4e95af08a 100644 --- a/store/adapters/rdbms/dal/connection.go +++ b/store/adapters/rdbms/dal/connection.go @@ -22,6 +22,14 @@ type ( } ) +func init() { + dal.RegisterDriver(dal.Driver{ + Type: "corteza::dal:driver:rdbms", + Capabilities: capabilities.FullCapabilities(), + Connection: dal.NewDSNDriverConnectionConfig(), + }) +} + func Connection(db *sqlx.DB, dialect drivers.Dialect, cc ...capabilities.Capability) *connection { return &connection{ db: db, diff --git a/store/adapters/rdbms/drivers/mysql/dal.go b/store/adapters/rdbms/drivers/mysql/dal.go index 9185ae15f..7e83ff62c 100644 --- a/store/adapters/rdbms/drivers/mysql/dal.go +++ b/store/adapters/rdbms/drivers/mysql/dal.go @@ -9,7 +9,7 @@ import ( ) func init() { - dal.Register(dalConnector, baseSchema, debugSchema) + dal.RegisterConnector(dalConnector, baseSchema, debugSchema) } func dalConnector(ctx context.Context, dsn string, cc ...capabilities.Capability) (_ dal.Connection, err error) { diff --git a/store/adapters/rdbms/drivers/postgres/dal.go b/store/adapters/rdbms/drivers/postgres/dal.go index c4721231b..4dfe38113 100644 --- a/store/adapters/rdbms/drivers/postgres/dal.go +++ b/store/adapters/rdbms/drivers/postgres/dal.go @@ -12,7 +12,7 @@ import ( ) func init() { - dal.Register(dalConnector, baseSchema, debugSchema) + dal.RegisterConnector(dalConnector, baseSchema, debugSchema) } func dalConnector(ctx context.Context, dsn string, cc ...capabilities.Capability) (_ dal.Connection, err error) { diff --git a/store/adapters/rdbms/drivers/sqlite/dal.go b/store/adapters/rdbms/drivers/sqlite/dal.go index d15cd7a3e..0615dcbf6 100644 --- a/store/adapters/rdbms/drivers/sqlite/dal.go +++ b/store/adapters/rdbms/drivers/sqlite/dal.go @@ -12,7 +12,7 @@ import ( ) func init() { - dal.Register(dalConnector, baseSchema, altSchema, debugSchema) + dal.RegisterConnector(dalConnector, baseSchema, altSchema, debugSchema) } func dalConnector(ctx context.Context, dsn string, cc ...capabilities.Capability) (_ dal.Connection, err error) { diff --git a/store/adapters/rdbms/filters.gen.go b/store/adapters/rdbms/filters.gen.go index ab2a2fed4..4b6b75ba4 100644 --- a/store/adapters/rdbms/filters.gen.go +++ b/store/adapters/rdbms/filters.gen.go @@ -95,6 +95,9 @@ type ( // optional dalConnection filter function called after the generated function DalConnection func(*Store, systemType.DalConnectionFilter) ([]goqu.Expression, systemType.DalConnectionFilter, error) + // optional dalSensitivityLevel filter function called after the generated function + DalSensitivityLevel func(*Store, systemType.DalSensitivityLevelFilter) ([]goqu.Expression, systemType.DalSensitivityLevelFilter, error) + // optional federationExposedModule filter function called after the generated function FederationExposedModule func(*Store, federationType.ExposedModuleFilter) ([]goqu.Expression, federationType.ExposedModuleFilter, error) @@ -737,20 +740,24 @@ func DalConnectionFilter(f systemType.DalConnectionFilter) (ee []goqu.Expression ee = append(ee, goqu.C("handle").Eq(f.Handle)) } - if val := strings.TrimSpace(f.DSN); len(val) > 0 { - ee = append(ee, goqu.C("dsn").Eq(f.DSN)) + return ee, f, err +} + +// DalSensitivityLevelFilter returns logical expressions +// +// This function is called from Store.QueryDalSensitivityLevels() and can be extended +// by setting Store.Filters.DalSensitivityLevel. Extension is called after all expressions +// are generated and can choose to ignore or alter them. +// +// This function is auto-generated +func DalSensitivityLevelFilter(f systemType.DalSensitivityLevelFilter) (ee []goqu.Expression, _ systemType.DalSensitivityLevelFilter, err error) { + + if expr := stateNilComparison("deleted_at", f.Deleted); expr != nil { + ee = append(ee, expr) } - if val := strings.TrimSpace(f.Location); len(val) > 0 { - ee = append(ee, goqu.C("location").Eq(f.Location)) - } - - if val := strings.TrimSpace(f.Ownership); len(val) > 0 { - ee = append(ee, goqu.C("ownership").Eq(f.Ownership)) - } - - if len(f.LabeledIDs) > 0 { - ee = append(ee, goqu.I("id").In(f.LabeledIDs)) + if len(f.SensitivityLevelID) > 0 { + ee = append(ee, goqu.C("id").In(f.SensitivityLevelID)) } return ee, f, err diff --git a/store/adapters/rdbms/queries.gen.go b/store/adapters/rdbms/queries.gen.go index a0d6de4bc..041dd55a8 100644 --- a/store/adapters/rdbms/queries.gen.go +++ b/store/adapters/rdbms/queries.gen.go @@ -2408,11 +2408,12 @@ var ( dalConnectionSelectQuery = func(d goqu.DialectWrapper) *goqu.SelectDataset { return d.Select( "id", + "name", "handle", - "dsn", + "type", "location", "ownership", - "sensitive", + "sensitivity_level", "config", "capabilities", "created_at", @@ -2430,20 +2431,21 @@ var ( dalConnectionInsertQuery = func(d goqu.DialectWrapper, res *systemType.DalConnection) *goqu.InsertDataset { return d.Insert(dalConnectionTable). Rows(goqu.Record{ - "id": res.ID, - "handle": res.Handle, - "dsn": res.DSN, - "location": res.Location, - "ownership": res.Ownership, - "sensitive": res.Sensitive, - "config": res.Config, - "capabilities": res.Capabilities, - "created_at": res.CreatedAt, - "updated_at": res.UpdatedAt, - "deleted_at": res.DeletedAt, - "created_by": res.CreatedBy, - "updated_by": res.UpdatedBy, - "deleted_by": res.DeletedBy, + "id": res.ID, + "name": res.Name, + "handle": res.Handle, + "type": res.Type, + "location": res.Location, + "ownership": res.Ownership, + "sensitivity_level": res.SensitivityLevel, + "config": res.Config, + "capabilities": res.Capabilities, + "created_at": res.CreatedAt, + "updated_at": res.UpdatedAt, + "deleted_at": res.DeletedAt, + "created_by": res.CreatedBy, + "updated_by": res.UpdatedBy, + "deleted_by": res.DeletedBy, }) } @@ -2457,19 +2459,20 @@ var ( OnConflict( goqu.DoUpdate(target[1:], goqu.Record{ - "handle": res.Handle, - "dsn": res.DSN, - "location": res.Location, - "ownership": res.Ownership, - "sensitive": res.Sensitive, - "config": res.Config, - "capabilities": res.Capabilities, - "created_at": res.CreatedAt, - "updated_at": res.UpdatedAt, - "deleted_at": res.DeletedAt, - "created_by": res.CreatedBy, - "updated_by": res.UpdatedBy, - "deleted_by": res.DeletedBy, + "name": res.Name, + "handle": res.Handle, + "type": res.Type, + "location": res.Location, + "ownership": res.Ownership, + "sensitivity_level": res.SensitivityLevel, + "config": res.Config, + "capabilities": res.Capabilities, + "created_at": res.CreatedAt, + "updated_at": res.UpdatedAt, + "deleted_at": res.DeletedAt, + "created_by": res.CreatedBy, + "updated_by": res.UpdatedBy, + "deleted_by": res.DeletedBy, }, ), ) @@ -2481,19 +2484,20 @@ var ( dalConnectionUpdateQuery = func(d goqu.DialectWrapper, res *systemType.DalConnection) *goqu.UpdateDataset { return d.Update(dalConnectionTable). Set(goqu.Record{ - "handle": res.Handle, - "dsn": res.DSN, - "location": res.Location, - "ownership": res.Ownership, - "sensitive": res.Sensitive, - "config": res.Config, - "capabilities": res.Capabilities, - "created_at": res.CreatedAt, - "updated_at": res.UpdatedAt, - "deleted_at": res.DeletedAt, - "created_by": res.CreatedBy, - "updated_by": res.UpdatedBy, - "deleted_by": res.DeletedBy, + "name": res.Name, + "handle": res.Handle, + "type": res.Type, + "location": res.Location, + "ownership": res.Ownership, + "sensitivity_level": res.SensitivityLevel, + "config": res.Config, + "capabilities": res.Capabilities, + "created_at": res.CreatedAt, + "updated_at": res.UpdatedAt, + "deleted_at": res.DeletedAt, + "created_by": res.CreatedBy, + "updated_by": res.UpdatedBy, + "deleted_by": res.DeletedBy, }). Where(dalConnectionPrimaryKeys(res)) } @@ -2521,6 +2525,114 @@ var ( } } + // dalSensitivityLevelTable represents dalSensitivityLevels store table + // + // This value is auto-generated + dalSensitivityLevelTable = goqu.T("dal_sensitivity_levels") + + // dalSensitivityLevelSelectQuery assembles select query for fetching dalSensitivityLevels + // + // This function is auto-generated + dalSensitivityLevelSelectQuery = func(d goqu.DialectWrapper) *goqu.SelectDataset { + return d.Select( + "id", + "handle", + "level", + "meta", + "created_at", + "updated_at", + "deleted_at", + "created_by", + "updated_by", + "deleted_by", + ).From(dalSensitivityLevelTable) + } + + // dalSensitivityLevelInsertQuery assembles query inserting dalSensitivityLevels + // + // This function is auto-generated + dalSensitivityLevelInsertQuery = func(d goqu.DialectWrapper, res *systemType.DalSensitivityLevel) *goqu.InsertDataset { + return d.Insert(dalSensitivityLevelTable). + Rows(goqu.Record{ + "id": res.ID, + "handle": res.Handle, + "level": res.Level, + "meta": res.Meta, + "created_at": res.CreatedAt, + "updated_at": res.UpdatedAt, + "deleted_at": res.DeletedAt, + "created_by": res.CreatedBy, + "updated_by": res.UpdatedBy, + "deleted_by": res.DeletedBy, + }) + } + + // dalSensitivityLevelUpsertQuery assembles (insert+on-conflict) query for replacing dalSensitivityLevels + // + // This function is auto-generated + dalSensitivityLevelUpsertQuery = func(d goqu.DialectWrapper, res *systemType.DalSensitivityLevel) *goqu.InsertDataset { + var target = `,id` + + return dalSensitivityLevelInsertQuery(d, res). + OnConflict( + goqu.DoUpdate(target[1:], + goqu.Record{ + "handle": res.Handle, + "level": res.Level, + "meta": res.Meta, + "created_at": res.CreatedAt, + "updated_at": res.UpdatedAt, + "deleted_at": res.DeletedAt, + "created_by": res.CreatedBy, + "updated_by": res.UpdatedBy, + "deleted_by": res.DeletedBy, + }, + ), + ) + } + + // dalSensitivityLevelUpdateQuery assembles query for updating dalSensitivityLevels + // + // This function is auto-generated + dalSensitivityLevelUpdateQuery = func(d goqu.DialectWrapper, res *systemType.DalSensitivityLevel) *goqu.UpdateDataset { + return d.Update(dalSensitivityLevelTable). + Set(goqu.Record{ + "handle": res.Handle, + "level": res.Level, + "meta": res.Meta, + "created_at": res.CreatedAt, + "updated_at": res.UpdatedAt, + "deleted_at": res.DeletedAt, + "created_by": res.CreatedBy, + "updated_by": res.UpdatedBy, + "deleted_by": res.DeletedBy, + }). + Where(dalSensitivityLevelPrimaryKeys(res)) + } + + // dalSensitivityLevelDeleteQuery assembles delete query for removing dalSensitivityLevels + // + // This function is auto-generated + dalSensitivityLevelDeleteQuery = func(d goqu.DialectWrapper, ee ...goqu.Expression) *goqu.DeleteDataset { + return d.Delete(dalSensitivityLevelTable).Where(ee...) + } + + // dalSensitivityLevelDeleteQuery assembles delete query for removing dalSensitivityLevels + // + // This function is auto-generated + dalSensitivityLevelTruncateQuery = func(d goqu.DialectWrapper) *goqu.TruncateDataset { + return d.Truncate(dalSensitivityLevelTable) + } + + // dalSensitivityLevelPrimaryKeys assembles set of conditions for all primary keys + // + // This function is auto-generated + dalSensitivityLevelPrimaryKeys = func(res *systemType.DalSensitivityLevel) goqu.Ex { + return goqu.Ex{ + "id": res.ID, + } + } + // federationExposedModuleTable represents federationExposedModules store table // // This value is auto-generated diff --git a/store/adapters/rdbms/rdbms.gen.go b/store/adapters/rdbms/rdbms.gen.go index 86a959143..538d4304d 100644 --- a/store/adapters/rdbms/rdbms.gen.go +++ b/store/adapters/rdbms/rdbms.gen.go @@ -51,6 +51,7 @@ var ( _ store.ComposeRecordValues = &Store{} _ store.Credentials = &Store{} _ store.DalConnections = &Store{} + _ store.DalSensitivityLevels = &Store{} _ store.FederationExposedModules = &Store{} _ store.FederationModuleMappings = &Store{} _ store.FederationNodes = &Store{} @@ -9623,41 +9624,7 @@ func (s Store) TruncateDalConnections(ctx context.Context) error { // This function is auto-generated func (s *Store) SearchDalConnections(ctx context.Context, f systemType.DalConnectionFilter) (set systemType.DalConnectionSet, _ systemType.DalConnectionFilter, err error) { - // Cleanup unwanted cursor values (only relevant is f.PageCursor, next&prev are reset and returned) - f.PrevPage, f.NextPage = nil, nil - - if f.PageCursor != nil { - // Page cursor exists; we need to validate it against used sort - // To cover the case when paging cursor is set but sorting is empty, we collect the sorting instructions - // from the cursor. - // This (extracted sorting info) is then returned as part of response - if f.Sort, err = f.PageCursor.Sort(f.Sort); err != nil { - return - } - } - - // Make sure results are always sorted at least by primary keys - if f.Sort.Get("id") == nil { - f.Sort = append(f.Sort, &filter.SortExpr{ - Column: "id", - Descending: f.Sort.LastDescending(), - }) - } - - // Cloned sorting instructions for the actual sorting - // Original are passed to the etchFullPageOfDalConnections fn used for cursor creation; - // direction information it MUST keep the initial - sort := f.Sort.Clone() - - // When cursor for a previous page is used it's marked as reversed - // This tells us to flip the descending flag on all used sort keys - if f.PageCursor != nil && f.PageCursor.ROrder { - sort.Reverse() - } - - set, f.PrevPage, f.NextPage, err = s.fetchFullPageOfDalConnections(ctx, f, sort) - - f.PageCursor = nil + set, _, err = s.QueryDalConnections(ctx, f) if err != nil { return nil, f, err } @@ -9665,133 +9632,6 @@ func (s *Store) SearchDalConnections(ctx context.Context, f systemType.DalConnec return set, f, nil } -// fetchFullPageOfDalConnections collects all requested results. -// -// Function applies: -// - cursor conditions (where ...) -// - limit -// -// Main responsibility of this function is to perform additional sequential queries in case when not enough results -// are collected due to failed check on a specific row (by check fn). -// -// Function then moves cursor to the last item fetched -// -// This function is auto-generated -func (s *Store) fetchFullPageOfDalConnections( - ctx context.Context, - filter systemType.DalConnectionFilter, - sort filter.SortExprSet, -) (set []*systemType.DalConnection, prev, next *filter.PagingCursor, err error) { - var ( - aux []*systemType.DalConnection - - // When cursor for a previous page is used it's marked as reversed - // This tells us to flip the descending flag on all used sort keys - reversedOrder = filter.PageCursor != nil && filter.PageCursor.ROrder - - // Copy no. of required items to limit - // Limit will change when doing subsequent queries to fill - // the set with all required items - limit = filter.Limit - - reqItems = filter.Limit - - // cursor to prev. page is only calculated when cursor is used - hasPrev = filter.PageCursor != nil - - // next cursor is calculated when there are more pages to come - hasNext bool - - tryFilter systemType.DalConnectionFilter - ) - - set = make([]*systemType.DalConnection, 0, DefaultSliceCapacity) - - for try := 0; try < MaxRefetches; try++ { - // Copy filter & apply custom sorting that might be affected by cursor - tryFilter = filter - tryFilter.Sort = sort - - if limit > 0 { - // fetching + 1 to peak ahead if there are more items - // we can fetch (next-page cursor) - tryFilter.Limit = limit + 1 - } - - if aux, hasNext, err = s.QueryDalConnections(ctx, tryFilter); err != nil { - return nil, nil, nil, err - } - - if len(aux) == 0 { - // nothing fetched - break - } - - // append fetched items - set = append(set, aux...) - - if reqItems == 0 || !hasNext { - // no max requested items specified, break out - break - } - - collected := uint(len(set)) - - if reqItems > collected { - // not enough items fetched, try again with adjusted limit - limit = reqItems - collected - - if limit < MinEnsureFetchLimit { - // In case limit is set very low and we've missed records in the first fetch, - // make sure next fetch limit is a bit higher - limit = MinEnsureFetchLimit - } - - // Update cursor so that it points to the last item fetched - tryFilter.PageCursor = s.collectDalConnectionCursorValues(set[collected-1], filter.Sort...) - - // Copy reverse flag from sorting - tryFilter.PageCursor.LThen = filter.Sort.Reversed() - continue - } - - if reqItems < collected { - set = set[:reqItems] - } - - break - } - - collected := len(set) - - if collected == 0 { - return nil, nil, nil, nil - } - - if reversedOrder { - // Fetched set needs to be reversed because we've forced a descending order to get the previous page - for i, j := 0, collected-1; i < j; i, j = i+1, j-1 { - set[i], set[j] = set[j], set[i] - } - - // when in reverse-order rules on what cursor to return change - hasPrev, hasNext = hasNext, hasPrev - } - - if hasPrev { - prev = s.collectDalConnectionCursorValues(set[0], filter.Sort...) - prev.ROrder = true - prev.LThen = !filter.Sort.Reversed() - } - - if hasNext { - next = s.collectDalConnectionCursorValues(set[collected-1], filter.Sort...) - next.LThen = filter.Sort.Reversed() - } - - return set, prev, next, nil -} - // QueryDalConnections queries the database, converts and checks each row and returns collected set // // With generics, we can remove this per-resource-generated function @@ -9811,8 +9651,6 @@ func (s *Store) QueryDalConnections( rows *sql.Rows count uint expr, tExpr []goqu.Expression - - sortExpr []exp.OrderedExpression ) if s.Filters.DalConnection != nil { @@ -9830,27 +9668,8 @@ func (s *Store) QueryDalConnections( expr = append(expr, tExpr...) - // paging feature is enabled - if f.PageCursor != nil { - if tExpr, err = cursor(f.PageCursor); err != nil { - return - } else { - expr = append(expr, tExpr...) - } - } - query := dalConnectionSelectQuery(s.Dialect).Where(expr...) - // sorting feature is enabled - if sortExpr, err = order(f.Sort, s.sortableDalConnectionFields()); err != nil { - err = fmt.Errorf("could generate order expression for DalConnection: %w", err) - return - } - - if len(sortExpr) > 0 { - query = query.Order(sortExpr...) - } - if f.Limit > 0 { query = query.Limit(f.Limit) } @@ -9905,7 +9724,7 @@ func (s *Store) QueryDalConnections( set = append(set, res) } - return set, f.Limit > 0 && count >= f.Limit, err + return set, false, err } @@ -10098,6 +9917,312 @@ func (s *Store) checkDalConnectionConstraints(ctx context.Context, res *systemTy return nil } +// CreateDalSensitivityLevel creates one or more rows in dalSensitivityLevel collection +// +// This function is auto-generated +func (s *Store) CreateDalSensitivityLevel(ctx context.Context, rr ...*systemType.DalSensitivityLevel) (err error) { + for i := range rr { + if err = s.checkDalSensitivityLevelConstraints(ctx, rr[i]); err != nil { + return + } + + if err = s.Exec(ctx, dalSensitivityLevelInsertQuery(s.Dialect, rr[i])); err != nil { + return + } + } + + return +} + +// UpdateDalSensitivityLevel updates one or more existing entries in dalSensitivityLevel collection +// +// This function is auto-generated +func (s *Store) UpdateDalSensitivityLevel(ctx context.Context, rr ...*systemType.DalSensitivityLevel) (err error) { + for i := range rr { + if err = s.checkDalSensitivityLevelConstraints(ctx, rr[i]); err != nil { + return + } + + if err = s.Exec(ctx, dalSensitivityLevelUpdateQuery(s.Dialect, rr[i])); err != nil { + return + } + } + + return +} + +// UpsertDalSensitivityLevel updates one or more existing entries in dalSensitivityLevel collection +// +// This function is auto-generated +func (s *Store) UpsertDalSensitivityLevel(ctx context.Context, rr ...*systemType.DalSensitivityLevel) (err error) { + for i := range rr { + if err = s.checkDalSensitivityLevelConstraints(ctx, rr[i]); err != nil { + return + } + + if err = s.Exec(ctx, dalSensitivityLevelUpsertQuery(s.Dialect, rr[i])); err != nil { + return + } + } + + return +} + +// DeleteDalSensitivityLevel Deletes one or more entries from dalSensitivityLevel collection +// +// This function is auto-generated +func (s *Store) DeleteDalSensitivityLevel(ctx context.Context, rr ...*systemType.DalSensitivityLevel) (err error) { + for i := range rr { + if err = s.Exec(ctx, dalSensitivityLevelDeleteQuery(s.Dialect, dalSensitivityLevelPrimaryKeys(rr[i]))); err != nil { + return + } + } + + return nil +} + +// DeleteDalSensitivityLevelByID deletes single entry from dalSensitivityLevel collection +// +// This function is auto-generated +func (s *Store) DeleteDalSensitivityLevelByID(ctx context.Context, id uint64) error { + return s.Exec(ctx, dalSensitivityLevelDeleteQuery(s.Dialect, goqu.Ex{ + "id": id, + })) +} + +// TruncateDalSensitivityLevels Deletes all rows from the dalSensitivityLevel collection +func (s Store) TruncateDalSensitivityLevels(ctx context.Context) error { + return s.Exec(ctx, dalSensitivityLevelTruncateQuery(s.Dialect)) +} + +// SearchDalSensitivityLevels returns (filtered) set of DalSensitivityLevels +// +// This function is auto-generated +func (s *Store) SearchDalSensitivityLevels(ctx context.Context, f systemType.DalSensitivityLevelFilter) (set systemType.DalSensitivityLevelSet, _ systemType.DalSensitivityLevelFilter, err error) { + + set, _, err = s.QueryDalSensitivityLevels(ctx, f) + if err != nil { + return nil, f, err + } + + return set, f, nil +} + +// QueryDalSensitivityLevels queries the database, converts and checks each row and returns collected set +// +// With generics, we can remove this per-resource-generated function +// and replace it with a single utility fetcher +// +// This function is auto-generated +func (s *Store) QueryDalSensitivityLevels( + ctx context.Context, + f systemType.DalSensitivityLevelFilter, +) (_ []*systemType.DalSensitivityLevel, more bool, err error) { + var ( + ok bool + + set = make([]*systemType.DalSensitivityLevel, 0, DefaultSliceCapacity) + res *systemType.DalSensitivityLevel + aux *auxDalSensitivityLevel + rows *sql.Rows + count uint + expr, tExpr []goqu.Expression + ) + + if s.Filters.DalSensitivityLevel != nil { + // extended filter set + tExpr, f, err = s.Filters.DalSensitivityLevel(s, f) + } else { + // using generated filter + tExpr, f, err = DalSensitivityLevelFilter(f) + } + + if err != nil { + err = fmt.Errorf("could generate filter expression for DalSensitivityLevel: %w", err) + return + } + + expr = append(expr, tExpr...) + + query := dalSensitivityLevelSelectQuery(s.Dialect).Where(expr...) + + if f.Limit > 0 { + query = query.Limit(f.Limit) + } + + rows, err = s.Query(ctx, query) + if err != nil { + err = fmt.Errorf("could not query DalSensitivityLevel: %w", err) + return + } + + if err = rows.Err(); err != nil { + err = fmt.Errorf("could not query DalSensitivityLevel: %w", err) + return + } + + defer func() { + closeError := rows.Close() + if err == nil { + // return error from close + err = closeError + } + }() + + for rows.Next() { + if err = rows.Err(); err != nil { + err = fmt.Errorf("could not query DalSensitivityLevel: %w", err) + return + } + + aux = new(auxDalSensitivityLevel) + if err = aux.scan(rows); err != nil { + err = fmt.Errorf("could not scan rows for DalSensitivityLevel: %w", err) + return + } + + count++ + if res, err = aux.decode(); err != nil { + err = fmt.Errorf("could not decode DalSensitivityLevel: %w", err) + return + } + + // check fn set, call it and see if it passed the test + // if not, skip the item + if f.Check != nil { + if ok, err = f.Check(res); err != nil { + return + } else if !ok { + continue + } + } + + set = append(set, res) + } + + return set, false, err + +} + +// LookupDalSensitivityLevelByID searches for user by ID +// +// It returns user even if deleted or suspended +// +// This function is auto-generated +func (s *Store) LookupDalSensitivityLevelByID(ctx context.Context, id uint64) (_ *systemType.DalSensitivityLevel, err error) { + var ( + rows *sql.Rows + aux = new(auxDalSensitivityLevel) + lookup = dalSensitivityLevelSelectQuery(s.Dialect).Where( + goqu.I("id").Eq(id), + ).Limit(1) + ) + + rows, err = s.Query(ctx, lookup) + if err != nil { + return + } + + defer func() { + closeError := rows.Close() + if err == nil { + // return error from close + err = closeError + } + }() + + if err = rows.Err(); err != nil { + return + } + + if !rows.Next() { + return nil, store.ErrNotFound.Stack(1) + } + + if err = aux.scan(rows); err != nil { + return + } + + return aux.decode() +} + +// sortableDalSensitivityLevelFields returns all columns flagged as sortable +// +// With optional string arg, all columns are returned aliased +// +// This function is auto-generated +func (Store) sortableDalSensitivityLevelFields() map[string]string { + return map[string]string{ + "created_at": "created_at", + "createdat": "created_at", + "deleted_at": "deleted_at", + "deletedat": "deleted_at", + "handle": "handle", + "id": "id", + "updated_at": "updated_at", + "updatedat": "updated_at", + } +} + +// collectDalSensitivityLevelCursorValues collects values from the given resource that and sets them to the cursor +// to be used for pagination +// +// Values that are collected must come from sortable, unique or primary columns/fields +// At least one of the collected columns must be flagged as unique, otherwise fn appends primary keys at the end +// +// Known issue: +// when collecting cursor values for query that sorts by unique column with partial index (ie: unique handle on +// undeleted items) +// +// This function is auto-generated +func (s *Store) collectDalSensitivityLevelCursorValues(res *systemType.DalSensitivityLevel, cc ...*filter.SortExpr) *filter.PagingCursor { + var ( + cur = &filter.PagingCursor{LThen: filter.SortExprSet(cc).Reversed()} + + hasUnique bool + + pkID bool + + collect = func(cc ...*filter.SortExpr) { + for _, c := range cc { + switch c.Column { + case "id": + cur.Set(c.Column, res.ID, c.Descending) + pkID = true + case "handle": + cur.Set(c.Column, res.Handle, c.Descending) + hasUnique = true + case "createdAt": + cur.Set(c.Column, res.CreatedAt, c.Descending) + case "updatedAt": + cur.Set(c.Column, res.UpdatedAt, c.Descending) + case "deletedAt": + cur.Set(c.Column, res.DeletedAt, c.Descending) + } + } + } + ) + + collect(cc...) + if !hasUnique || !pkID { + collect(&filter.SortExpr{Column: "id", Descending: false}) + } + + return cur + +} + +// checkDalSensitivityLevelConstraints performs lookups (on valid) resource to check if any of the values on unique fields +// already exists in the store +// +// Using built-in constraint checking would be more performant, but unfortunately we cannot rely +// on the full support (MySQL does not support conditional indexes) +// +// This function is auto-generated +func (s *Store) checkDalSensitivityLevelConstraints(ctx context.Context, res *systemType.DalSensitivityLevel) (err error) { + return nil +} + // CreateFederationExposedModule creates one or more rows in federationExposedModule collection // // This function is auto-generated diff --git a/store/adapters/rdbms/upgrade_tables.go b/store/adapters/rdbms/upgrade_tables.go index 8a7f3d96f..5ae1777b8 100644 --- a/store/adapters/rdbms/upgrade_tables.go +++ b/store/adapters/rdbms/upgrade_tables.go @@ -32,7 +32,8 @@ const ( func Tables() []*Table { return []*Table{ tableUsers(), - tableConnections(), + tableDalConnections(), + tableDalSensitivityLevels(), tableCredentials(), tableAuthClients(), tableAuthConfirmedClients(), @@ -95,15 +96,18 @@ func tableUsers() *Table { ) } -func tableConnections() *Table { +func tableDalConnections() *Table { return TableDef("dal_connections", ID, ColumnDef("handle", ColumnTypeVarchar, ColumnTypeLength(handleLength)), - ColumnDef("dsn", ColumnTypeVarchar, ColumnTypeLength(urlLength)), - ColumnDef("location", ColumnTypeText), + ColumnDef("name", ColumnTypeText), + ColumnDef("type", ColumnTypeText), + + ColumnDef("location", ColumnTypeJson), ColumnDef("ownership", ColumnTypeText), - ColumnDef("sensitive", ColumnTypeBoolean), + ColumnDef("sensitivity_level", ColumnTypeIdentifier), + ColumnDef("config", ColumnTypeJson), ColumnDef("capabilities", ColumnTypeJson), CUDTimestamps, @@ -113,6 +117,22 @@ func tableConnections() *Table { ) } +func tableDalSensitivityLevels() *Table { + return TableDef("dal_sensitivity_levels", + ID, + + ColumnDef("handle", ColumnTypeVarchar, ColumnTypeLength(handleLength)), + ColumnDef("level", ColumnTypeInteger), + + ColumnDef("meta", ColumnTypeJson), + + CUDTimestamps, + CUDUsers, + + AddIndex("unique_handle", IExpr("LOWER(handle)"), IWhere("LENGTH(handle) > 0 AND deleted_at IS NULL")), + ) +} + func tableCredentials() *Table { return TableDef(`credentials`, ID, diff --git a/store/interfaces.gen.go b/store/interfaces.gen.go index 5f66f28bc..51650f18d 100644 --- a/store/interfaces.gen.go +++ b/store/interfaces.gen.go @@ -61,6 +61,7 @@ type ( ComposeRecordValues Credentials DalConnections + DalSensitivityLevels FederationExposedModules FederationModuleMappings FederationNodes @@ -351,6 +352,17 @@ type ( LookupDalConnectionByHandle(ctx context.Context, handle string) (*systemType.DalConnection, error) } + DalSensitivityLevels interface { + SearchDalSensitivityLevels(ctx context.Context, f systemType.DalSensitivityLevelFilter) (systemType.DalSensitivityLevelSet, systemType.DalSensitivityLevelFilter, error) + CreateDalSensitivityLevel(ctx context.Context, rr ...*systemType.DalSensitivityLevel) error + UpdateDalSensitivityLevel(ctx context.Context, rr ...*systemType.DalSensitivityLevel) error + UpsertDalSensitivityLevel(ctx context.Context, rr ...*systemType.DalSensitivityLevel) error + DeleteDalSensitivityLevel(ctx context.Context, rr ...*systemType.DalSensitivityLevel) error + DeleteDalSensitivityLevelByID(ctx context.Context, id uint64) error + TruncateDalSensitivityLevels(ctx context.Context) error + LookupDalSensitivityLevelByID(ctx context.Context, id uint64) (*systemType.DalSensitivityLevel, error) + } + FederationExposedModules interface { SearchFederationExposedModules(ctx context.Context, f federationType.ExposedModuleFilter) (federationType.ExposedModuleSet, federationType.ExposedModuleFilter, error) CreateFederationExposedModule(ctx context.Context, rr ...*federationType.ExposedModule) error @@ -2031,6 +2043,64 @@ func LookupDalConnectionByHandle(ctx context.Context, s DalConnections, handle s return s.LookupDalConnectionByHandle(ctx, handle) } +// SearchDalSensitivityLevels returns all matching DalSensitivityLevels from store +// +// This function is auto-generated +func SearchDalSensitivityLevels(ctx context.Context, s DalSensitivityLevels, f systemType.DalSensitivityLevelFilter) (systemType.DalSensitivityLevelSet, systemType.DalSensitivityLevelFilter, error) { + return s.SearchDalSensitivityLevels(ctx, f) +} + +// CreateDalSensitivityLevel creates one or more DalSensitivityLevels in store +// +// This function is auto-generated +func CreateDalSensitivityLevel(ctx context.Context, s DalSensitivityLevels, rr ...*systemType.DalSensitivityLevel) error { + return s.CreateDalSensitivityLevel(ctx, rr...) +} + +// UpdateDalSensitivityLevel updates one or more (existing) DalSensitivityLevels in store +// +// This function is auto-generated +func UpdateDalSensitivityLevel(ctx context.Context, s DalSensitivityLevels, rr ...*systemType.DalSensitivityLevel) error { + return s.UpdateDalSensitivityLevel(ctx, rr...) +} + +// UpsertDalSensitivityLevel creates new or updates existing one or more DalSensitivityLevels in store +// +// This function is auto-generated +func UpsertDalSensitivityLevel(ctx context.Context, s DalSensitivityLevels, rr ...*systemType.DalSensitivityLevel) error { + return s.UpsertDalSensitivityLevel(ctx, rr...) +} + +// DeleteDalSensitivityLevel deletes one or more DalSensitivityLevels from store +// +// This function is auto-generated +func DeleteDalSensitivityLevel(ctx context.Context, s DalSensitivityLevels, rr ...*systemType.DalSensitivityLevel) error { + return s.DeleteDalSensitivityLevel(ctx, rr...) +} + +// DeleteDalSensitivityLevelByID deletes one or more DalSensitivityLevels from store +// +// This function is auto-generated +func DeleteDalSensitivityLevelByID(ctx context.Context, s DalSensitivityLevels, id uint64) error { + return s.DeleteDalSensitivityLevelByID(ctx, id) +} + +// TruncateDalSensitivityLevels Deletes all DalSensitivityLevels from store +// +// This function is auto-generated +func TruncateDalSensitivityLevels(ctx context.Context, s DalSensitivityLevels) error { + return s.TruncateDalSensitivityLevels(ctx) +} + +// LookupDalSensitivityLevelByID searches for user by ID +// +// It returns user even if deleted or suspended +// +// This function is auto-generated +func LookupDalSensitivityLevelByID(ctx context.Context, s DalSensitivityLevels, id uint64) (*systemType.DalSensitivityLevel, error) { + return s.LookupDalSensitivityLevelByID(ctx, id) +} + // SearchFederationExposedModules returns all matching FederationExposedModules from store // // This function is auto-generated diff --git a/store/tests/all_test.go b/store/tests/all_test.go index 5972b58a7..504c31ef7 100644 --- a/store/tests/all_test.go +++ b/store/tests/all_test.go @@ -80,6 +80,9 @@ func testAllGenerated(t *testing.T, s store.Storer) { t.Run("dalConnection", func(t *testing.T) { testDalConnections(t, s) }) + t.Run("dalSensitivityLevel", func(t *testing.T) { + testDalSensitivityLevels(t, s) + }) t.Run("federationExposedModule", func(t *testing.T) { testFederationExposedModules(t, s) }) diff --git a/system/component.cue b/system/component.cue index fcf480efb..ec031bd1c 100644 --- a/system/component.cue +++ b/system/component.cue @@ -28,6 +28,7 @@ component: schema.#component & { "template": template "user": user "dal_connection": dal_connection + "dal_sensitivity_level": dal_sensitivity_level } rbac: operations: { @@ -47,6 +48,8 @@ component: schema.#component & { "dal-connection.create": description: "Create DAL connections" "dal-connections.search": description: "List, search or filter DAL connections" + "dal-sensitivity-level.manage": description: "Can manage DAL sensitivity levels" + "application.create": description: "Create applications" "applications.search": description: "List, search or filter auth clients" "application.flag.self": description: "Manage private flags for applications" diff --git a/system/dal_connection.cue b/system/dal_connection.cue index e7360f95e..6cdfbd09a 100644 --- a/system/dal_connection.cue +++ b/system/dal_connection.cue @@ -7,11 +7,15 @@ import ( dal_connection: schema.#Resource & { struct: { id: schema.IdField + name: { goType: "string" } handle: schema.HandleField - dsn: {expIdent: "DSN"} - location: {} + + // omitting isPrimary and replacing with a special type + type: { goType: "string" } + + location: { goType: "*geolocation.Full" } ownership: {} - sensitive: {goType: "bool"} + sensitivity_level: { goType: "uint64" } config: {goType: "types.ConnectionConfig"} capabilities: {goType: "types.ConnectionCapabilities"} @@ -28,18 +32,21 @@ dal_connection: schema.#Resource & { struct: { connection_id: {goType: "[]uint64", ident: "connectionID", storeIdent: "id"} handle: {goType: "string"} - dsn: {expIdent: "DSN", goType: "string"} - location: {goType: "string"} - ownership: {goType: "string"} - sensitive: {goType: "bool"} + type: {goType: "string"} deleted: {goType: "filter.State", storeIdent: "deleted_at"} } - byValue: ["connection_id", "handle", "dsn", "location", "ownership"] + byValue: ["connection_id", "handle"] byNilState: ["deleted"] } + features: { + labels: false + paging: false + sorting: false + } + rbac: { operations: { "read": description: "Read connection" diff --git a/system/dal_sensitivity_level.cue b/system/dal_sensitivity_level.cue new file mode 100644 index 000000000..d07f2c68a --- /dev/null +++ b/system/dal_sensitivity_level.cue @@ -0,0 +1,57 @@ +package system + +import ( + "github.com/cortezaproject/corteza-server/codegen/schema" +) + +dal_sensitivity_level: schema.#Resource & { + struct: { + id: schema.IdField + handle: schema.HandleField + level: { goType: "int" } + meta: {goType: "types.DalSensitivityLevelMeta"} + + created_at: schema.SortableTimestampField + updated_at: schema.SortableTimestampNilField + deleted_at: schema.SortableTimestampNilField + created_by: { goType: "uint64" } + updated_by: { goType: "uint64" } + deleted_by: { goType: "uint64" } + } + + filter: { + struct: { + sensitivity_level_id: {goType: "[]uint64", ident: "sensitivityLevelID", storeIdent: "id"} + + deleted: {goType: "filter.State", storeIdent: "deleted_at"} + } + + byValue: ["sensitivity_level_id"] + byNilState: ["deleted"] + } + + rbac: { + operations: {} + } + + features: { + labels: false + paging: false + sorting: false + } + + store: { + api: { + lookups: [ + { + fields: ["id"] + description: """ + searches for user by ID + + It returns user even if deleted or suspended + """ + } + ] + } + } +} diff --git a/system/rest.yaml b/system/rest.yaml index 512cf8bc5..79a3ce1fb 100644 --- a/system/rest.yaml +++ b/system/rest.yaml @@ -701,6 +701,121 @@ endpoints: required: true title: File import +- title: Data access layer drivers + path: "/dal/drivers" + entrypoint: dalDriver + authentication: + - Client ID + - Session ID + apis: + - name: list + method: GET + title: Search drivers + path: "/" + +- title: Data access layer sensitivity levels + path: "/dal/sensitivity-levels" + entrypoint: dalSensitivityLevel + authentication: + - Client ID + - Session ID + imports: + - github.com/cortezaproject/corteza-server/system/types + apis: + - name: list + method: GET + title: Search sensitivity levels + path: "/" + parameters: + get: + - name: sensitivityLevelID + type: "[]string" + required: false + title: Filter by sensitivity level ID + - name: deleted + required: false + title: Exclude (0, default), include (1) or return only (2) deleted sensitivity levels + type: uint + + - name: create + method: POST + title: Create sensitivity level + path: "/" + parameters: + post: + - name: handle + type: string + required: true + title: handle + - name: level + type: int + required: true + title: level + - name: meta + type: types.DalSensitivityLevelMeta + parser: types.ParseDalSensitivityLevelMeta + required: true + title: meta + + - name: update + method: PUT + title: Update connection details + path: "/{sensitivityLevelID}" + parameters: + path: + - type: uint64 + name: sensitivityLevelID + required: true + title: Connection ID + post: + - name: handle + type: string + required: true + title: handle + - name: level + type: int + required: true + title: level + - name: meta + type: types.DalSensitivityLevelMeta + parser: types.ParseDalSensitivityLevelMeta + required: true + title: meta + + - name: read + method: GET + title: Read connection details + path: "/{sensitivityLevelID}" + parameters: + path: + - type: uint64 + name: sensitivityLevelID + required: true + title: Connection ID + + - name: delete + method: DELETE + title: Remove sensitivity level + path: "/{sensitivityLevelID}" + parameters: + path: + - type: uint64 + name: sensitivityLevelID + required: true + title: Connection ID + + - name: undelete + method: POST + title: Undelete sensitivity level + path: "/{sensitivityLevelID}/undelete" + parameters: + path: + - type: uint64 + name: sensitivityLevelID + required: true + title: Connection ID + + - title: Data access layer connections path: "/dal/connections" entrypoint: dalConnection @@ -708,8 +823,8 @@ endpoints: - Client ID - Session ID imports: - - github.com/cortezaproject/corteza-server/pkg/label - github.com/cortezaproject/corteza-server/system/types + - github.com/cortezaproject/corteza-server/pkg/geolocation apis: - name: list method: GET @@ -726,30 +841,13 @@ endpoints: required: false title: Search handle to match against connections - type: string - name: location + name: type required: false - title: Search location to match against connections - - type: string - name: ownership - required: false - title: Search ownership to match against connections + title: Search type to match against connections - name: deleted required: false title: Exclude (0, default), include (1) or return only (2) deleted connections type: uint - - type: map[string]string - name: labels - title: Labels - parser: label.ParseStrings - - type: uint - name: limit - title: Limit - - type: string - name: pageCursor - title: Page cursor - - type: string - name: sort - title: Sort items - name: create method: POST title: Create connection @@ -760,22 +858,29 @@ endpoints: type: string required: true title: handle - - name: dsn + - name: name type: string required: true - title: dsn - - name: location + title: name + - name: type type: string required: true + title: type + + - name: location + type: "*geolocation.Full" + required: true title: location + parser: geolocation.Parse - name: ownership type: string required: true title: ownership - - name: sensitive - type: bool + - name: sensitivityLevel + type: uint64 required: true - title: sensitive + title: sensitivityLevel + - name: config type: types.ConnectionConfig required: true @@ -786,10 +891,6 @@ endpoints: required: true title: capabilities parser: types.ParseConnectionCapabilities - - type: map[string]string - name: labels - title: Labels - parser: label.ParseStrings - name: update method: PUT title: Update connection details @@ -805,22 +906,29 @@ endpoints: type: string required: true title: handle - - name: dsn + - name: name type: string required: true - title: dsn - - name: location + title: name + - name: type type: string required: true + title: type + + - name: location + type: "*geolocation.Full" + required: true title: location + parser: geolocation.Parse - name: ownership type: string required: true title: ownership - - name: sensitive - type: bool + - name: sensitivityLevel + type: uint64 required: true - title: sensitive + title: sensitivityLevel + - name: config type: types.ConnectionConfig required: true @@ -831,14 +939,6 @@ endpoints: required: true title: capabilities parser: types.ParseConnectionCapabilities - - type: map[string]string - name: labels - title: Labels - parser: label.ParseStrings - - name: readPrimary - method: GET - title: Read primary connection details - path: "/primary" - name: read method: GET title: Read connection details diff --git a/system/rest/connection.go b/system/rest/connection.go deleted file mode 100644 index 2dd7196fb..000000000 --- a/system/rest/connection.go +++ /dev/null @@ -1,159 +0,0 @@ -package rest - -import ( - "context" - "io" - "net/http" - "time" - - "github.com/cortezaproject/corteza-server/pkg/api" - "github.com/cortezaproject/corteza-server/pkg/filter" - "github.com/cortezaproject/corteza-server/pkg/payload" - "github.com/cortezaproject/corteza-server/system/rest/request" - "github.com/cortezaproject/corteza-server/system/service" - "github.com/cortezaproject/corteza-server/system/types" - "github.com/pkg/errors" -) - -var _ = errors.Wrap - -type ( - Connection struct { - svc connectionService - connectionAc connectionAccessController - } - - connectionSetPayload struct { - Filter types.DalConnectionFilter `json:"filter"` - Set types.DalConnectionSet `json:"set"` - } - - connectionAccessController interface { - CanCreateDalConnection(context.Context) bool - CanUpdateDalConnection(context.Context, *types.DalConnection) bool - } - - connectionService interface { - FindByID(ctx context.Context, ID uint64) (*types.DalConnection, error) - Create(ctx context.Context, new *types.DalConnection) (*types.DalConnection, error) - Update(ctx context.Context, upd *types.DalConnection) (*types.DalConnection, error) - DeleteByID(ctx context.Context, ID uint64) error - UndeleteByID(ctx context.Context, ID uint64) error - Search(ctx context.Context, filter types.DalConnectionFilter) (types.DalConnectionSet, types.DalConnectionFilter, error) - } -) - -func (Connection) New() *Connection { - return &Connection{ - svc: service.DefaultConnection, - connectionAc: service.DefaultAccessControl, - } -} - -func (ctrl Connection) List(ctx context.Context, r *request.ConnectionList) (interface{}, error) { - var ( - err error - set types.DalConnectionSet - f = types.DalConnectionFilter{ - ConnectionID: payload.ParseUint64s(r.ConnectionID), - Handle: r.Handle, - Location: r.Location, - Ownership: r.Ownership, - - Labels: r.Labels, - Deleted: filter.State(r.Deleted), - } - ) - - if f.Paging, err = filter.NewPaging(r.Limit, r.PageCursor); err != nil { - return nil, err - } - - if f.Sorting, err = filter.NewSorting(r.Sort); err != nil { - return nil, err - } - - if f.Deleted == 0 { - f.Deleted = filter.StateInclusive - } - - set, f, err = ctrl.svc.Search(ctx, f) - return ctrl.makeFilterPayload(ctx, set, f, err) -} - -func (ctrl Connection) Create(ctx context.Context, r *request.ConnectionCreate) (interface{}, error) { - connection := &types.DalConnection{ - Handle: r.Handle, - - DSN: r.Dsn, - Location: r.Location, - Ownership: r.Ownership, - Sensitive: r.Sensitive, - - Config: r.Config, - Capabilities: r.Capabilities, - - Labels: r.Labels, - } - - return ctrl.svc.Create(ctx, connection) -} - -func (ctrl Connection) Update(ctx context.Context, r *request.ConnectionUpdate) (interface{}, error) { - connection := &types.DalConnection{ - ID: r.ConnectionID, - Handle: r.Handle, - - DSN: r.Dsn, - Location: r.Location, - Ownership: r.Ownership, - Sensitive: r.Sensitive, - - Config: r.Config, - Capabilities: r.Capabilities, - - Labels: r.Labels, - } - - return ctrl.svc.Update(ctx, connection) -} - -func (ctrl Connection) ReadPrimary(ctx context.Context, r *request.ConnectionReadPrimary) (interface{}, error) { - return ctrl.svc.FindByID(ctx, 0) -} - -func (ctrl Connection) Read(ctx context.Context, r *request.ConnectionRead) (interface{}, error) { - return ctrl.svc.FindByID(ctx, r.ConnectionID) -} - -func (ctrl Connection) Delete(ctx context.Context, r *request.ConnectionDelete) (interface{}, error) { - return api.OK(), ctrl.svc.DeleteByID(ctx, r.ConnectionID) -} - -func (ctrl Connection) Undelete(ctx context.Context, r *request.ConnectionUndelete) (interface{}, error) { - return api.OK(), ctrl.svc.UndeleteByID(ctx, r.ConnectionID) -} - -func (ctrl Connection) makeFilterPayload(ctx context.Context, uu types.DalConnectionSet, f types.DalConnectionFilter, err error) (*connectionSetPayload, error) { - if err != nil { - return nil, err - } - - if len(uu) == 0 { - uu = make([]*types.DalConnection, 0) - } - - return &connectionSetPayload{Filter: f, Set: uu}, nil -} - -func (ctrl Connection) serve(ctx context.Context, fn string, archive io.ReadSeeker, err error) (interface{}, error) { - if err != nil { - return nil, err - } - - return func(w http.ResponseWriter, req *http.Request) { - w.Header().Add("Content-Disposition", "attachment; filename="+fn) - - http.ServeContent(w, req, fn, time.Now(), archive) - }, nil -} diff --git a/system/rest/dal_connection.go b/system/rest/dal_connection.go new file mode 100644 index 000000000..3d4e83325 --- /dev/null +++ b/system/rest/dal_connection.go @@ -0,0 +1,286 @@ +package rest + +import ( + "context" + "fmt" + "io" + "net/http" + "time" + + federationService "github.com/cortezaproject/corteza-server/federation/service" + federationTypes "github.com/cortezaproject/corteza-server/federation/types" + "github.com/cortezaproject/corteza-server/pkg/api" + "github.com/cortezaproject/corteza-server/pkg/dal" + "github.com/cortezaproject/corteza-server/pkg/filter" + "github.com/cortezaproject/corteza-server/pkg/handle" + "github.com/cortezaproject/corteza-server/pkg/payload" + "github.com/cortezaproject/corteza-server/system/rest/request" + "github.com/cortezaproject/corteza-server/system/service" + "github.com/cortezaproject/corteza-server/system/types" + "github.com/modern-go/reflect2" + "github.com/pkg/errors" +) + +var _ = errors.Wrap + +type ( + DalConnection struct { + svc connectionService + federationSvc federationNodeService + + connectionAc connectionAccessController + } + + connectionWrap struct { + types.DalConnection + + Type string `json:"type"` + Primary bool `json:"primary"` + } + connectionWrapSet []connectionWrap + + connectionSetPayload struct { + Filter types.DalConnectionFilter `json:"filter"` + Set types.DalConnectionSet `json:"set"` + } + + connectionAccessController interface { + CanCreateDalConnection(context.Context) bool + CanUpdateDalConnection(context.Context, *types.DalConnection) bool + } + + connectionService interface { + FindByID(ctx context.Context, ID uint64) (*types.DalConnection, error) + FindPrimary(ctx context.Context) (*types.DalConnection, error) + Create(ctx context.Context, new *types.DalConnection) (*types.DalConnection, error) + Update(ctx context.Context, upd *types.DalConnection) (*types.DalConnection, error) + DeleteByID(ctx context.Context, ID uint64) error + UndeleteByID(ctx context.Context, ID uint64) error + Search(ctx context.Context, filter types.DalConnectionFilter) (types.DalConnectionSet, types.DalConnectionFilter, error) + } + + federationNodeService interface { + Search(ctx context.Context, filter federationTypes.NodeFilter) (set federationTypes.NodeSet, f federationTypes.NodeFilter, err error) + } +) + +func (DalConnection) New() *DalConnection { + return &DalConnection{ + svc: service.DefaultDalConnection, + federationSvc: federationService.DefaultNode, + + connectionAc: service.DefaultAccessControl, + } +} + +func (ctrl DalConnection) List(ctx context.Context, r *request.DalConnectionList) (interface{}, error) { + var ( + err error + dalConnections types.DalConnectionSet + + f = types.DalConnectionFilter{ + ConnectionID: payload.ParseUint64s(r.ConnectionID), + Handle: r.Handle, + Type: r.Type, + + Deleted: filter.State(r.Deleted), + } + ) + + if f.Deleted == 0 { + f.Deleted = filter.StateInclusive + } + + dalConnections, err = ctrl.collectConnections(ctx, f) + if err != nil { + return nil, err + } + + return ctrl.makeFilterPayload(ctx, dalConnections, f) +} + +func (ctrl DalConnection) Create(ctx context.Context, r *request.DalConnectionCreate) (interface{}, error) { + connection := &types.DalConnection{ + Name: r.Name, + Handle: r.Handle, + Type: r.Type, + + Location: r.Location, + Ownership: r.Ownership, + SensitivityLevel: r.SensitivityLevel, + + Config: r.Config, + Capabilities: r.Capabilities, + } + + switch connection.Type { + case types.DalConnectionResourceType: + return ctrl.svc.Create(ctx, connection) + default: + return nil, fmt.Errorf("cannot create connection: unsupported connection type %s", connection.Type) + } + +} + +func (ctrl DalConnection) Update(ctx context.Context, r *request.DalConnectionUpdate) (interface{}, error) { + connection := &types.DalConnection{ + ID: r.ConnectionID, + Name: r.Name, + Handle: r.Handle, + Type: r.Type, + + Location: r.Location, + Ownership: r.Ownership, + SensitivityLevel: r.SensitivityLevel, + + Config: r.Config, + Capabilities: r.Capabilities, + } + + return ctrl.svc.Update(ctx, connection) +} + +func (ctrl DalConnection) Read(ctx context.Context, r *request.DalConnectionRead) (interface{}, error) { + return ctrl.svc.FindByID(ctx, r.ConnectionID) +} + +func (ctrl DalConnection) Delete(ctx context.Context, r *request.DalConnectionDelete) (interface{}, error) { + return api.OK(), ctrl.svc.DeleteByID(ctx, r.ConnectionID) +} + +func (ctrl DalConnection) Undelete(ctx context.Context, r *request.DalConnectionUndelete) (interface{}, error) { + return api.OK(), ctrl.svc.UndeleteByID(ctx, r.ConnectionID) +} + +func (ctrl DalConnection) makeFilterPayload(ctx context.Context, connections types.DalConnectionSet, f types.DalConnectionFilter) (out *connectionSetPayload, err error) { + out = &connectionSetPayload{ + Set: connections, + Filter: f, + } + + return +} + +func (ctrl DalConnection) federatedNodeToConnection(f *federationTypes.Node) *types.DalConnection { + h, _ := handle.Cast(nil, f.Name) + + return &types.DalConnection{ + ID: f.ID, + Name: f.Name, + Handle: h, + Type: federationTypes.NodeResourceType, + Location: nil, + Ownership: f.Contact, + + Config: types.ConnectionConfig{ + Connection: dal.NewFederatedNodeCOnnection(f.BaseURL, f.PairToken, f.AuthToken), + }, + + CreatedAt: f.CreatedAt, + CreatedBy: f.CreatedBy, + UpdatedAt: f.UpdatedAt, + UpdatedBy: f.UpdatedBy, + DeletedAt: f.DeletedAt, + DeletedBy: f.DeletedBy, + } +} + +func (ctrl DalConnection) collectConnections(ctx context.Context, f types.DalConnectionFilter) (out types.DalConnectionSet, err error) { + var ( + dalConnections types.DalConnectionSet + primaryDalConnection *types.DalConnection + federatedNodes federationTypes.NodeSet + ) + + if dalConnections, f, err = ctrl.svc.Search(ctx, f); err != nil { + return nil, err + } + + if primaryDalConnection, err = ctrl.svc.FindPrimary(ctx); err != nil { + return nil, err + } + + if !reflect2.IsNil(ctrl.federationSvc) { + if federatedNodes, _, err = ctrl.federationSvc.Search(ctx, federationTypes.NodeFilter{ + // @todo IDs? + Deleted: f.Deleted, + }); err != nil { + return nil, err + } + } + + out = append(out, primaryDalConnection) + out = append(out, dalConnections...) + + // We're converting federation nodes to DAL connection structs so that we have + // a unified output. + // + // Eventually federation nodes will become connections, so this is ok + for _, f := range federatedNodes { + out = append(out, ctrl.federatedNodeToConnection(f)) + } + + out = ctrl.filterConnections(out, f) + + return +} + +func (ctrl DalConnection) filterConnections(baseConnections types.DalConnectionSet, f types.DalConnectionFilter) (out types.DalConnectionSet) { + for _, conn := range baseConnections { + include := true + + if len(f.ConnectionID) > 0 { + include = include && ctrl.inIDSet(f.ConnectionID, conn.ID) + } + + if f.Handle != "" { + include = include && f.Handle == conn.Handle + } + + if f.Type != "" { + include = include && f.Type == conn.Type + } + + { + if f.Deleted == filter.StateExcluded { + include = include && conn.DeletedAt == nil + } + + if f.Deleted == filter.StateExclusive { + include = include && conn.DeletedAt != nil + } + } + + if f.Check != nil { + // @todo error handling here? + tmp, _ := f.Check(conn) + include = include && tmp + } + + if include { + out = append(out, conn) + } + } + + return +} + +func (ctrl DalConnection) inIDSet(set []uint64, target uint64) (out bool) { + for _, id := range set { + out = out || id == target + } + + return +} + +func (ctrl DalConnection) serve(ctx context.Context, fn string, archive io.ReadSeeker, err error) (interface{}, error) { + if err != nil { + return nil, err + } + + return func(w http.ResponseWriter, req *http.Request) { + w.Header().Add("Content-Disposition", "attachment; filename="+fn) + + http.ServeContent(w, req, fn, time.Now(), archive) + }, nil +} diff --git a/system/rest/dal_drivers.go b/system/rest/dal_drivers.go new file mode 100644 index 000000000..a4d513dd1 --- /dev/null +++ b/system/rest/dal_drivers.go @@ -0,0 +1,50 @@ +package rest + +import ( + "context" + "io" + "net/http" + "time" + + "github.com/cortezaproject/corteza-server/pkg/dal" + "github.com/cortezaproject/corteza-server/system/rest/request" + "github.com/pkg/errors" +) + +var _ = errors.Wrap + +type ( + DalDriver struct{} + + dalDriverSetPayload struct { + Set []dal.Driver `json:"set"` + } +) + +func (DalDriver) New() *DalDriver { + return &DalDriver{} +} + +func (ctrl DalDriver) List(ctx context.Context, r *request.DalDriverList) (interface{}, error) { + return ctrl.makeFilterPayload(ctx, dal.Service().Drivers()) +} + +func (ctrl DalDriver) makeFilterPayload(ctx context.Context, drivers []dal.Driver) (out *dalDriverSetPayload, err error) { + out = &dalDriverSetPayload{ + Set: drivers, + } + + return +} + +func (ctrl DalDriver) serve(ctx context.Context, fn string, archive io.ReadSeeker, err error) (interface{}, error) { + if err != nil { + return nil, err + } + + return func(w http.ResponseWriter, req *http.Request) { + w.Header().Add("Content-Disposition", "attachment; filename="+fn) + + http.ServeContent(w, req, fn, time.Now(), archive) + }, nil +} diff --git a/system/rest/handlers/dalConnection.go b/system/rest/handlers/dalConnection.go index 5f1490edd..b1308186e 100644 --- a/system/rest/handlers/dalConnection.go +++ b/system/rest/handlers/dalConnection.go @@ -22,7 +22,6 @@ type ( List(context.Context, *request.DalConnectionList) (interface{}, error) Create(context.Context, *request.DalConnectionCreate) (interface{}, error) Update(context.Context, *request.DalConnectionUpdate) (interface{}, error) - ReadPrimary(context.Context, *request.DalConnectionReadPrimary) (interface{}, error) Read(context.Context, *request.DalConnectionRead) (interface{}, error) Delete(context.Context, *request.DalConnectionDelete) (interface{}, error) Undelete(context.Context, *request.DalConnectionUndelete) (interface{}, error) @@ -30,13 +29,12 @@ type ( // HTTP API interface DalConnection struct { - List func(http.ResponseWriter, *http.Request) - Create func(http.ResponseWriter, *http.Request) - Update func(http.ResponseWriter, *http.Request) - ReadPrimary func(http.ResponseWriter, *http.Request) - Read func(http.ResponseWriter, *http.Request) - Delete func(http.ResponseWriter, *http.Request) - Undelete func(http.ResponseWriter, *http.Request) + List func(http.ResponseWriter, *http.Request) + Create func(http.ResponseWriter, *http.Request) + Update func(http.ResponseWriter, *http.Request) + Read func(http.ResponseWriter, *http.Request) + Delete func(http.ResponseWriter, *http.Request) + Undelete func(http.ResponseWriter, *http.Request) } ) @@ -90,22 +88,6 @@ func NewDalConnection(h DalConnectionAPI) *DalConnection { api.Send(w, r, value) }, - ReadPrimary: func(w http.ResponseWriter, r *http.Request) { - defer r.Body.Close() - params := request.NewDalConnectionReadPrimary() - if err := params.Fill(r); err != nil { - api.Send(w, r, err) - return - } - - value, err := h.ReadPrimary(r.Context(), params) - if err != nil { - api.Send(w, r, err) - return - } - - api.Send(w, r, value) - }, Read: func(w http.ResponseWriter, r *http.Request) { defer r.Body.Close() params := request.NewDalConnectionRead() @@ -163,7 +145,6 @@ func (h DalConnection) MountRoutes(r chi.Router, middlewares ...func(http.Handle r.Get("/dal/connections/", h.List) r.Post("/dal/connections/", h.Create) r.Put("/dal/connections/{connectionID}", h.Update) - r.Get("/dal/connections/primary", h.ReadPrimary) r.Get("/dal/connections/{connectionID}", h.Read) r.Delete("/dal/connections/{connectionID}", h.Delete) r.Post("/dal/connections/{connectionID}/undelete", h.Undelete) diff --git a/system/rest/handlers/dalDriver.go b/system/rest/handlers/dalDriver.go new file mode 100644 index 000000000..b6e51d794 --- /dev/null +++ b/system/rest/handlers/dalDriver.go @@ -0,0 +1,57 @@ +package handlers + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// + +import ( + "context" + "github.com/cortezaproject/corteza-server/pkg/api" + "github.com/cortezaproject/corteza-server/system/rest/request" + "github.com/go-chi/chi/v5" + "net/http" +) + +type ( + // Internal API interface + DalDriverAPI interface { + List(context.Context, *request.DalDriverList) (interface{}, error) + } + + // HTTP API interface + DalDriver struct { + List func(http.ResponseWriter, *http.Request) + } +) + +func NewDalDriver(h DalDriverAPI) *DalDriver { + return &DalDriver{ + List: func(w http.ResponseWriter, r *http.Request) { + defer r.Body.Close() + params := request.NewDalDriverList() + if err := params.Fill(r); err != nil { + api.Send(w, r, err) + return + } + + value, err := h.List(r.Context(), params) + if err != nil { + api.Send(w, r, err) + return + } + + api.Send(w, r, value) + }, + } +} + +func (h DalDriver) MountRoutes(r chi.Router, middlewares ...func(http.Handler) http.Handler) { + r.Group(func(r chi.Router) { + r.Use(middlewares...) + r.Get("/dal/drivers/", h.List) + }) +} diff --git a/system/rest/handlers/dalSensitivityLevel.go b/system/rest/handlers/dalSensitivityLevel.go new file mode 100644 index 000000000..b6e530727 --- /dev/null +++ b/system/rest/handlers/dalSensitivityLevel.go @@ -0,0 +1,152 @@ +package handlers + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// + +import ( + "context" + "github.com/cortezaproject/corteza-server/pkg/api" + "github.com/cortezaproject/corteza-server/system/rest/request" + "github.com/go-chi/chi/v5" + "net/http" +) + +type ( + // Internal API interface + DalSensitivityLevelAPI interface { + List(context.Context, *request.DalSensitivityLevelList) (interface{}, error) + Create(context.Context, *request.DalSensitivityLevelCreate) (interface{}, error) + Update(context.Context, *request.DalSensitivityLevelUpdate) (interface{}, error) + Read(context.Context, *request.DalSensitivityLevelRead) (interface{}, error) + Delete(context.Context, *request.DalSensitivityLevelDelete) (interface{}, error) + Undelete(context.Context, *request.DalSensitivityLevelUndelete) (interface{}, error) + } + + // HTTP API interface + DalSensitivityLevel struct { + List func(http.ResponseWriter, *http.Request) + Create func(http.ResponseWriter, *http.Request) + Update func(http.ResponseWriter, *http.Request) + Read func(http.ResponseWriter, *http.Request) + Delete func(http.ResponseWriter, *http.Request) + Undelete func(http.ResponseWriter, *http.Request) + } +) + +func NewDalSensitivityLevel(h DalSensitivityLevelAPI) *DalSensitivityLevel { + return &DalSensitivityLevel{ + List: func(w http.ResponseWriter, r *http.Request) { + defer r.Body.Close() + params := request.NewDalSensitivityLevelList() + if err := params.Fill(r); err != nil { + api.Send(w, r, err) + return + } + + value, err := h.List(r.Context(), params) + if err != nil { + api.Send(w, r, err) + return + } + + api.Send(w, r, value) + }, + Create: func(w http.ResponseWriter, r *http.Request) { + defer r.Body.Close() + params := request.NewDalSensitivityLevelCreate() + if err := params.Fill(r); err != nil { + api.Send(w, r, err) + return + } + + value, err := h.Create(r.Context(), params) + if err != nil { + api.Send(w, r, err) + return + } + + api.Send(w, r, value) + }, + Update: func(w http.ResponseWriter, r *http.Request) { + defer r.Body.Close() + params := request.NewDalSensitivityLevelUpdate() + if err := params.Fill(r); err != nil { + api.Send(w, r, err) + return + } + + value, err := h.Update(r.Context(), params) + if err != nil { + api.Send(w, r, err) + return + } + + api.Send(w, r, value) + }, + Read: func(w http.ResponseWriter, r *http.Request) { + defer r.Body.Close() + params := request.NewDalSensitivityLevelRead() + if err := params.Fill(r); err != nil { + api.Send(w, r, err) + return + } + + value, err := h.Read(r.Context(), params) + if err != nil { + api.Send(w, r, err) + return + } + + api.Send(w, r, value) + }, + Delete: func(w http.ResponseWriter, r *http.Request) { + defer r.Body.Close() + params := request.NewDalSensitivityLevelDelete() + if err := params.Fill(r); err != nil { + api.Send(w, r, err) + return + } + + value, err := h.Delete(r.Context(), params) + if err != nil { + api.Send(w, r, err) + return + } + + api.Send(w, r, value) + }, + Undelete: func(w http.ResponseWriter, r *http.Request) { + defer r.Body.Close() + params := request.NewDalSensitivityLevelUndelete() + if err := params.Fill(r); err != nil { + api.Send(w, r, err) + return + } + + value, err := h.Undelete(r.Context(), params) + if err != nil { + api.Send(w, r, err) + return + } + + api.Send(w, r, value) + }, + } +} + +func (h DalSensitivityLevel) MountRoutes(r chi.Router, middlewares ...func(http.Handler) http.Handler) { + r.Group(func(r chi.Router) { + r.Use(middlewares...) + r.Get("/dal/sensitivity-levels/", h.List) + r.Post("/dal/sensitivity-levels/", h.Create) + r.Put("/dal/sensitivity-levels/{sensitivityLevelID}", h.Update) + r.Get("/dal/sensitivity-levels/{sensitivityLevelID}", h.Read) + r.Delete("/dal/sensitivity-levels/{sensitivityLevelID}", h.Delete) + r.Post("/dal/sensitivity-levels/{sensitivityLevelID}/undelete", h.Undelete) + }) +} diff --git a/system/rest/request/dalConnection.go b/system/rest/request/dalConnection.go index 8b8b8a6e3..8d2741cfd 100644 --- a/system/rest/request/dalConnection.go +++ b/system/rest/request/dalConnection.go @@ -11,7 +11,7 @@ package request import ( "encoding/json" "fmt" - "github.com/cortezaproject/corteza-server/pkg/label" + "github.com/cortezaproject/corteza-server/pkg/geolocation" "github.com/cortezaproject/corteza-server/pkg/payload" "github.com/cortezaproject/corteza-server/system/types" "github.com/go-chi/chi/v5" @@ -46,40 +46,15 @@ type ( // Search handle to match against connections Handle string - // Location GET parameter + // Type GET parameter // - // Search location to match against connections - Location string - - // Ownership GET parameter - // - // Search ownership to match against connections - Ownership string + // Search type to match against connections + Type string // Deleted GET parameter // // Exclude (0, default), include (1) or return only (2) deleted connections Deleted uint - - // Labels GET parameter - // - // Labels - Labels map[string]string - - // Limit GET parameter - // - // Limit - Limit uint - - // PageCursor GET parameter - // - // Page cursor - PageCursor string - - // Sort GET parameter - // - // Sort items - Sort string } DalConnectionCreate struct { @@ -88,25 +63,30 @@ type ( // handle Handle string - // Dsn POST parameter + // Name POST parameter // - // dsn - Dsn string + // name + Name string + + // Type POST parameter + // + // type + Type string // Location POST parameter // // location - Location string + Location *geolocation.Full // Ownership POST parameter // // ownership Ownership string - // Sensitive POST parameter + // SensitivityLevel POST parameter // - // sensitive - Sensitive bool + // sensitivityLevel + SensitivityLevel uint64 `json:",string"` // Config POST parameter // @@ -117,11 +97,6 @@ type ( // // capabilities Capabilities types.ConnectionCapabilities - - // Labels POST parameter - // - // Labels - Labels map[string]string } DalConnectionUpdate struct { @@ -135,25 +110,30 @@ type ( // handle Handle string - // Dsn POST parameter + // Name POST parameter // - // dsn - Dsn string + // name + Name string + + // Type POST parameter + // + // type + Type string // Location POST parameter // // location - Location string + Location *geolocation.Full // Ownership POST parameter // // ownership Ownership string - // Sensitive POST parameter + // SensitivityLevel POST parameter // - // sensitive - Sensitive bool + // sensitivityLevel + SensitivityLevel uint64 `json:",string"` // Config POST parameter // @@ -164,14 +144,6 @@ type ( // // capabilities Capabilities types.ConnectionCapabilities - - // Labels POST parameter - // - // Labels - Labels map[string]string - } - - DalConnectionReadPrimary struct { } DalConnectionRead struct { @@ -206,13 +178,8 @@ func (r DalConnectionList) Auditable() map[string]interface{} { return map[string]interface{}{ "connectionID": r.ConnectionID, "handle": r.Handle, - "location": r.Location, - "ownership": r.Ownership, + "type": r.Type, "deleted": r.Deleted, - "labels": r.Labels, - "limit": r.Limit, - "pageCursor": r.PageCursor, - "sort": r.Sort, } } @@ -227,13 +194,8 @@ func (r DalConnectionList) GetHandle() string { } // Auditable returns all auditable/loggable parameters -func (r DalConnectionList) GetLocation() string { - return r.Location -} - -// Auditable returns all auditable/loggable parameters -func (r DalConnectionList) GetOwnership() string { - return r.Ownership +func (r DalConnectionList) GetType() string { + return r.Type } // Auditable returns all auditable/loggable parameters @@ -241,26 +203,6 @@ func (r DalConnectionList) GetDeleted() uint { return r.Deleted } -// Auditable returns all auditable/loggable parameters -func (r DalConnectionList) GetLabels() map[string]string { - return r.Labels -} - -// Auditable returns all auditable/loggable parameters -func (r DalConnectionList) GetLimit() uint { - return r.Limit -} - -// Auditable returns all auditable/loggable parameters -func (r DalConnectionList) GetPageCursor() string { - return r.PageCursor -} - -// Auditable returns all auditable/loggable parameters -func (r DalConnectionList) GetSort() string { - return r.Sort -} - // Fill processes request and fills internal variables func (r *DalConnectionList) Fill(req *http.Request) (err error) { @@ -285,14 +227,8 @@ func (r *DalConnectionList) Fill(req *http.Request) (err error) { return err } } - if val, ok := tmp["location"]; ok && len(val) > 0 { - r.Location, err = val[0], nil - if err != nil { - return err - } - } - if val, ok := tmp["ownership"]; ok && len(val) > 0 { - r.Ownership, err = val[0], nil + if val, ok := tmp["type"]; ok && len(val) > 0 { + r.Type, err = val[0], nil if err != nil { return err } @@ -303,35 +239,6 @@ func (r *DalConnectionList) Fill(req *http.Request) (err error) { return err } } - if val, ok := tmp["labels[]"]; ok { - r.Labels, err = label.ParseStrings(val) - if err != nil { - return err - } - } else if val, ok := tmp["labels"]; ok { - r.Labels, err = label.ParseStrings(val) - if err != nil { - return err - } - } - if val, ok := tmp["limit"]; ok && len(val) > 0 { - r.Limit, err = payload.ParseUint(val[0]), nil - if err != nil { - return err - } - } - if val, ok := tmp["pageCursor"]; ok && len(val) > 0 { - r.PageCursor, err = val[0], nil - if err != nil { - return err - } - } - if val, ok := tmp["sort"]; ok && len(val) > 0 { - r.Sort, err = val[0], nil - if err != nil { - return err - } - } } return err @@ -345,14 +252,14 @@ func NewDalConnectionCreate() *DalConnectionCreate { // Auditable returns all auditable/loggable parameters func (r DalConnectionCreate) Auditable() map[string]interface{} { return map[string]interface{}{ - "handle": r.Handle, - "dsn": r.Dsn, - "location": r.Location, - "ownership": r.Ownership, - "sensitive": r.Sensitive, - "config": r.Config, - "capabilities": r.Capabilities, - "labels": r.Labels, + "handle": r.Handle, + "name": r.Name, + "type": r.Type, + "location": r.Location, + "ownership": r.Ownership, + "sensitivityLevel": r.SensitivityLevel, + "config": r.Config, + "capabilities": r.Capabilities, } } @@ -362,12 +269,17 @@ func (r DalConnectionCreate) GetHandle() string { } // Auditable returns all auditable/loggable parameters -func (r DalConnectionCreate) GetDsn() string { - return r.Dsn +func (r DalConnectionCreate) GetName() string { + return r.Name } // Auditable returns all auditable/loggable parameters -func (r DalConnectionCreate) GetLocation() string { +func (r DalConnectionCreate) GetType() string { + return r.Type +} + +// Auditable returns all auditable/loggable parameters +func (r DalConnectionCreate) GetLocation() *geolocation.Full { return r.Location } @@ -377,8 +289,8 @@ func (r DalConnectionCreate) GetOwnership() string { } // Auditable returns all auditable/loggable parameters -func (r DalConnectionCreate) GetSensitive() bool { - return r.Sensitive +func (r DalConnectionCreate) GetSensitivityLevel() uint64 { + return r.SensitivityLevel } // Auditable returns all auditable/loggable parameters @@ -391,11 +303,6 @@ func (r DalConnectionCreate) GetCapabilities() types.ConnectionCapabilities { return r.Capabilities } -// Auditable returns all auditable/loggable parameters -func (r DalConnectionCreate) GetLabels() map[string]string { - return r.Labels -} - // Fill processes request and fills internal variables func (r *DalConnectionCreate) Fill(req *http.Request) (err error) { @@ -424,15 +331,27 @@ func (r *DalConnectionCreate) Fill(req *http.Request) (err error) { } } - if val, ok := req.MultipartForm.Value["dsn"]; ok && len(val) > 0 { - r.Dsn, err = val[0], nil + if val, ok := req.MultipartForm.Value["name"]; ok && len(val) > 0 { + r.Name, err = val[0], nil if err != nil { return err } } - if val, ok := req.MultipartForm.Value["location"]; ok && len(val) > 0 { - r.Location, err = val[0], nil + if val, ok := req.MultipartForm.Value["type"]; ok && len(val) > 0 { + r.Type, err = val[0], nil + if err != nil { + return err + } + } + + if val, ok := req.MultipartForm.Value["location[]"]; ok { + r.Location, err = geolocation.Parse(val) + if err != nil { + return err + } + } else if val, ok := req.MultipartForm.Value["location"]; ok { + r.Location, err = geolocation.Parse(val) if err != nil { return err } @@ -445,8 +364,8 @@ func (r *DalConnectionCreate) Fill(req *http.Request) (err error) { } } - if val, ok := req.MultipartForm.Value["sensitive"]; ok && len(val) > 0 { - r.Sensitive, err = payload.ParseBool(val[0]), nil + if val, ok := req.MultipartForm.Value["sensitivityLevel"]; ok && len(val) > 0 { + r.SensitivityLevel, err = payload.ParseUint64(val[0]), nil if err != nil { return err } @@ -475,18 +394,6 @@ func (r *DalConnectionCreate) Fill(req *http.Request) (err error) { return err } } - - if val, ok := req.MultipartForm.Value["labels[]"]; ok { - r.Labels, err = label.ParseStrings(val) - if err != nil { - return err - } - } else if val, ok := req.MultipartForm.Value["labels"]; ok { - r.Labels, err = label.ParseStrings(val) - if err != nil { - return err - } - } } } @@ -504,15 +411,27 @@ func (r *DalConnectionCreate) Fill(req *http.Request) (err error) { } } - if val, ok := req.Form["dsn"]; ok && len(val) > 0 { - r.Dsn, err = val[0], nil + if val, ok := req.Form["name"]; ok && len(val) > 0 { + r.Name, err = val[0], nil if err != nil { return err } } - if val, ok := req.Form["location"]; ok && len(val) > 0 { - r.Location, err = val[0], nil + if val, ok := req.Form["type"]; ok && len(val) > 0 { + r.Type, err = val[0], nil + if err != nil { + return err + } + } + + if val, ok := req.Form["location[]"]; ok { + r.Location, err = geolocation.Parse(val) + if err != nil { + return err + } + } else if val, ok := req.Form["location"]; ok { + r.Location, err = geolocation.Parse(val) if err != nil { return err } @@ -525,8 +444,8 @@ func (r *DalConnectionCreate) Fill(req *http.Request) (err error) { } } - if val, ok := req.Form["sensitive"]; ok && len(val) > 0 { - r.Sensitive, err = payload.ParseBool(val[0]), nil + if val, ok := req.Form["sensitivityLevel"]; ok && len(val) > 0 { + r.SensitivityLevel, err = payload.ParseUint64(val[0]), nil if err != nil { return err } @@ -555,18 +474,6 @@ func (r *DalConnectionCreate) Fill(req *http.Request) (err error) { return err } } - - if val, ok := req.Form["labels[]"]; ok { - r.Labels, err = label.ParseStrings(val) - if err != nil { - return err - } - } else if val, ok := req.Form["labels"]; ok { - r.Labels, err = label.ParseStrings(val) - if err != nil { - return err - } - } } return err @@ -580,15 +487,15 @@ func NewDalConnectionUpdate() *DalConnectionUpdate { // Auditable returns all auditable/loggable parameters func (r DalConnectionUpdate) Auditable() map[string]interface{} { return map[string]interface{}{ - "connectionID": r.ConnectionID, - "handle": r.Handle, - "dsn": r.Dsn, - "location": r.Location, - "ownership": r.Ownership, - "sensitive": r.Sensitive, - "config": r.Config, - "capabilities": r.Capabilities, - "labels": r.Labels, + "connectionID": r.ConnectionID, + "handle": r.Handle, + "name": r.Name, + "type": r.Type, + "location": r.Location, + "ownership": r.Ownership, + "sensitivityLevel": r.SensitivityLevel, + "config": r.Config, + "capabilities": r.Capabilities, } } @@ -603,12 +510,17 @@ func (r DalConnectionUpdate) GetHandle() string { } // Auditable returns all auditable/loggable parameters -func (r DalConnectionUpdate) GetDsn() string { - return r.Dsn +func (r DalConnectionUpdate) GetName() string { + return r.Name } // Auditable returns all auditable/loggable parameters -func (r DalConnectionUpdate) GetLocation() string { +func (r DalConnectionUpdate) GetType() string { + return r.Type +} + +// Auditable returns all auditable/loggable parameters +func (r DalConnectionUpdate) GetLocation() *geolocation.Full { return r.Location } @@ -618,8 +530,8 @@ func (r DalConnectionUpdate) GetOwnership() string { } // Auditable returns all auditable/loggable parameters -func (r DalConnectionUpdate) GetSensitive() bool { - return r.Sensitive +func (r DalConnectionUpdate) GetSensitivityLevel() uint64 { + return r.SensitivityLevel } // Auditable returns all auditable/loggable parameters @@ -632,11 +544,6 @@ func (r DalConnectionUpdate) GetCapabilities() types.ConnectionCapabilities { return r.Capabilities } -// Auditable returns all auditable/loggable parameters -func (r DalConnectionUpdate) GetLabels() map[string]string { - return r.Labels -} - // Fill processes request and fills internal variables func (r *DalConnectionUpdate) Fill(req *http.Request) (err error) { @@ -665,15 +572,27 @@ func (r *DalConnectionUpdate) Fill(req *http.Request) (err error) { } } - if val, ok := req.MultipartForm.Value["dsn"]; ok && len(val) > 0 { - r.Dsn, err = val[0], nil + if val, ok := req.MultipartForm.Value["name"]; ok && len(val) > 0 { + r.Name, err = val[0], nil if err != nil { return err } } - if val, ok := req.MultipartForm.Value["location"]; ok && len(val) > 0 { - r.Location, err = val[0], nil + if val, ok := req.MultipartForm.Value["type"]; ok && len(val) > 0 { + r.Type, err = val[0], nil + if err != nil { + return err + } + } + + if val, ok := req.MultipartForm.Value["location[]"]; ok { + r.Location, err = geolocation.Parse(val) + if err != nil { + return err + } + } else if val, ok := req.MultipartForm.Value["location"]; ok { + r.Location, err = geolocation.Parse(val) if err != nil { return err } @@ -686,8 +605,8 @@ func (r *DalConnectionUpdate) Fill(req *http.Request) (err error) { } } - if val, ok := req.MultipartForm.Value["sensitive"]; ok && len(val) > 0 { - r.Sensitive, err = payload.ParseBool(val[0]), nil + if val, ok := req.MultipartForm.Value["sensitivityLevel"]; ok && len(val) > 0 { + r.SensitivityLevel, err = payload.ParseUint64(val[0]), nil if err != nil { return err } @@ -716,18 +635,6 @@ func (r *DalConnectionUpdate) Fill(req *http.Request) (err error) { return err } } - - if val, ok := req.MultipartForm.Value["labels[]"]; ok { - r.Labels, err = label.ParseStrings(val) - if err != nil { - return err - } - } else if val, ok := req.MultipartForm.Value["labels"]; ok { - r.Labels, err = label.ParseStrings(val) - if err != nil { - return err - } - } } } @@ -745,15 +652,27 @@ func (r *DalConnectionUpdate) Fill(req *http.Request) (err error) { } } - if val, ok := req.Form["dsn"]; ok && len(val) > 0 { - r.Dsn, err = val[0], nil + if val, ok := req.Form["name"]; ok && len(val) > 0 { + r.Name, err = val[0], nil if err != nil { return err } } - if val, ok := req.Form["location"]; ok && len(val) > 0 { - r.Location, err = val[0], nil + if val, ok := req.Form["type"]; ok && len(val) > 0 { + r.Type, err = val[0], nil + if err != nil { + return err + } + } + + if val, ok := req.Form["location[]"]; ok { + r.Location, err = geolocation.Parse(val) + if err != nil { + return err + } + } else if val, ok := req.Form["location"]; ok { + r.Location, err = geolocation.Parse(val) if err != nil { return err } @@ -766,8 +685,8 @@ func (r *DalConnectionUpdate) Fill(req *http.Request) (err error) { } } - if val, ok := req.Form["sensitive"]; ok && len(val) > 0 { - r.Sensitive, err = payload.ParseBool(val[0]), nil + if val, ok := req.Form["sensitivityLevel"]; ok && len(val) > 0 { + r.SensitivityLevel, err = payload.ParseUint64(val[0]), nil if err != nil { return err } @@ -796,18 +715,6 @@ func (r *DalConnectionUpdate) Fill(req *http.Request) (err error) { return err } } - - if val, ok := req.Form["labels[]"]; ok { - r.Labels, err = label.ParseStrings(val) - if err != nil { - return err - } - } else if val, ok := req.Form["labels"]; ok { - r.Labels, err = label.ParseStrings(val) - if err != nil { - return err - } - } } { @@ -825,22 +732,6 @@ func (r *DalConnectionUpdate) Fill(req *http.Request) (err error) { return err } -// NewDalConnectionReadPrimary request -func NewDalConnectionReadPrimary() *DalConnectionReadPrimary { - return &DalConnectionReadPrimary{} -} - -// Auditable returns all auditable/loggable parameters -func (r DalConnectionReadPrimary) Auditable() map[string]interface{} { - return map[string]interface{}{} -} - -// Fill processes request and fills internal variables -func (r *DalConnectionReadPrimary) Fill(req *http.Request) (err error) { - - return err -} - // NewDalConnectionRead request func NewDalConnectionRead() *DalConnectionRead { return &DalConnectionRead{} diff --git a/system/rest/request/dalDriver.go b/system/rest/request/dalDriver.go new file mode 100644 index 000000000..5116c393e --- /dev/null +++ b/system/rest/request/dalDriver.go @@ -0,0 +1,54 @@ +package request + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// + +import ( + "encoding/json" + "fmt" + "github.com/cortezaproject/corteza-server/pkg/payload" + "github.com/go-chi/chi/v5" + "io" + "mime/multipart" + "net/http" + "strings" +) + +// dummy vars to prevent +// unused imports complain +var ( + _ = chi.URLParam + _ = multipart.ErrMessageTooLarge + _ = payload.ParseUint64s + _ = strings.ToLower + _ = io.EOF + _ = fmt.Errorf + _ = json.NewEncoder +) + +type ( + // Internal API interface + DalDriverList struct { + } +) + +// NewDalDriverList request +func NewDalDriverList() *DalDriverList { + return &DalDriverList{} +} + +// Auditable returns all auditable/loggable parameters +func (r DalDriverList) Auditable() map[string]interface{} { + return map[string]interface{}{} +} + +// Fill processes request and fills internal variables +func (r *DalDriverList) Fill(req *http.Request) (err error) { + + return err +} diff --git a/system/rest/request/dalSensitivityLevel.go b/system/rest/request/dalSensitivityLevel.go new file mode 100644 index 000000000..b0cb56555 --- /dev/null +++ b/system/rest/request/dalSensitivityLevel.go @@ -0,0 +1,513 @@ +package request + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// + +import ( + "encoding/json" + "fmt" + "github.com/cortezaproject/corteza-server/pkg/payload" + "github.com/cortezaproject/corteza-server/system/types" + "github.com/go-chi/chi/v5" + "io" + "mime/multipart" + "net/http" + "strings" +) + +// dummy vars to prevent +// unused imports complain +var ( + _ = chi.URLParam + _ = multipart.ErrMessageTooLarge + _ = payload.ParseUint64s + _ = strings.ToLower + _ = io.EOF + _ = fmt.Errorf + _ = json.NewEncoder +) + +type ( + // Internal API interface + DalSensitivityLevelList struct { + // SensitivityLevelID GET parameter + // + // Filter by sensitivity level ID + SensitivityLevelID []string + + // Deleted GET parameter + // + // Exclude (0, default), include (1) or return only (2) deleted sensitivity levels + Deleted uint + } + + DalSensitivityLevelCreate struct { + // Handle POST parameter + // + // handle + Handle string + + // Level POST parameter + // + // level + Level int + + // Meta POST parameter + // + // meta + Meta types.DalSensitivityLevelMeta + } + + DalSensitivityLevelUpdate struct { + // SensitivityLevelID PATH parameter + // + // Connection ID + SensitivityLevelID uint64 `json:",string"` + + // Handle POST parameter + // + // handle + Handle string + + // Level POST parameter + // + // level + Level int + + // Meta POST parameter + // + // meta + Meta types.DalSensitivityLevelMeta + } + + DalSensitivityLevelRead struct { + // SensitivityLevelID PATH parameter + // + // Connection ID + SensitivityLevelID uint64 `json:",string"` + } + + DalSensitivityLevelDelete struct { + // SensitivityLevelID PATH parameter + // + // Connection ID + SensitivityLevelID uint64 `json:",string"` + } + + DalSensitivityLevelUndelete struct { + // SensitivityLevelID PATH parameter + // + // Connection ID + SensitivityLevelID uint64 `json:",string"` + } +) + +// NewDalSensitivityLevelList request +func NewDalSensitivityLevelList() *DalSensitivityLevelList { + return &DalSensitivityLevelList{} +} + +// Auditable returns all auditable/loggable parameters +func (r DalSensitivityLevelList) Auditable() map[string]interface{} { + return map[string]interface{}{ + "sensitivityLevelID": r.SensitivityLevelID, + "deleted": r.Deleted, + } +} + +// Auditable returns all auditable/loggable parameters +func (r DalSensitivityLevelList) GetSensitivityLevelID() []string { + return r.SensitivityLevelID +} + +// Auditable returns all auditable/loggable parameters +func (r DalSensitivityLevelList) GetDeleted() uint { + return r.Deleted +} + +// Fill processes request and fills internal variables +func (r *DalSensitivityLevelList) Fill(req *http.Request) (err error) { + + { + // GET params + tmp := req.URL.Query() + + if val, ok := tmp["sensitivityLevelID[]"]; ok { + r.SensitivityLevelID, err = val, nil + if err != nil { + return err + } + } else if val, ok := tmp["sensitivityLevelID"]; ok { + r.SensitivityLevelID, err = val, nil + if err != nil { + return err + } + } + if val, ok := tmp["deleted"]; ok && len(val) > 0 { + r.Deleted, err = payload.ParseUint(val[0]), nil + if err != nil { + return err + } + } + } + + return err +} + +// NewDalSensitivityLevelCreate request +func NewDalSensitivityLevelCreate() *DalSensitivityLevelCreate { + return &DalSensitivityLevelCreate{} +} + +// Auditable returns all auditable/loggable parameters +func (r DalSensitivityLevelCreate) Auditable() map[string]interface{} { + return map[string]interface{}{ + "handle": r.Handle, + "level": r.Level, + "meta": r.Meta, + } +} + +// Auditable returns all auditable/loggable parameters +func (r DalSensitivityLevelCreate) GetHandle() string { + return r.Handle +} + +// Auditable returns all auditable/loggable parameters +func (r DalSensitivityLevelCreate) GetLevel() int { + return r.Level +} + +// Auditable returns all auditable/loggable parameters +func (r DalSensitivityLevelCreate) GetMeta() types.DalSensitivityLevelMeta { + return r.Meta +} + +// Fill processes request and fills internal variables +func (r *DalSensitivityLevelCreate) Fill(req *http.Request) (err error) { + + if strings.HasPrefix(strings.ToLower(req.Header.Get("content-type")), "application/json") { + err = json.NewDecoder(req.Body).Decode(r) + + switch { + case err == io.EOF: + err = nil + case err != nil: + return fmt.Errorf("error parsing http request body: %w", err) + } + } + + { + // Caching 32MB to memory, the rest to disk + if err = req.ParseMultipartForm(32 << 20); err != nil && err != http.ErrNotMultipart { + return err + } else if err == nil { + // Multipart params + + if val, ok := req.MultipartForm.Value["handle"]; ok && len(val) > 0 { + r.Handle, err = val[0], nil + if err != nil { + return err + } + } + + if val, ok := req.MultipartForm.Value["level"]; ok && len(val) > 0 { + r.Level, err = payload.ParseInt(val[0]), nil + if err != nil { + return err + } + } + + if val, ok := req.MultipartForm.Value["meta[]"]; ok { + r.Meta, err = types.ParseDalSensitivityLevelMeta(val) + if err != nil { + return err + } + } else if val, ok := req.MultipartForm.Value["meta"]; ok { + r.Meta, err = types.ParseDalSensitivityLevelMeta(val) + if err != nil { + return err + } + } + } + } + + { + if err = req.ParseForm(); err != nil { + return err + } + + // POST params + + if val, ok := req.Form["handle"]; ok && len(val) > 0 { + r.Handle, err = val[0], nil + if err != nil { + return err + } + } + + if val, ok := req.Form["level"]; ok && len(val) > 0 { + r.Level, err = payload.ParseInt(val[0]), nil + if err != nil { + return err + } + } + + if val, ok := req.Form["meta[]"]; ok { + r.Meta, err = types.ParseDalSensitivityLevelMeta(val) + if err != nil { + return err + } + } else if val, ok := req.Form["meta"]; ok { + r.Meta, err = types.ParseDalSensitivityLevelMeta(val) + if err != nil { + return err + } + } + } + + return err +} + +// NewDalSensitivityLevelUpdate request +func NewDalSensitivityLevelUpdate() *DalSensitivityLevelUpdate { + return &DalSensitivityLevelUpdate{} +} + +// Auditable returns all auditable/loggable parameters +func (r DalSensitivityLevelUpdate) Auditable() map[string]interface{} { + return map[string]interface{}{ + "sensitivityLevelID": r.SensitivityLevelID, + "handle": r.Handle, + "level": r.Level, + "meta": r.Meta, + } +} + +// Auditable returns all auditable/loggable parameters +func (r DalSensitivityLevelUpdate) GetSensitivityLevelID() uint64 { + return r.SensitivityLevelID +} + +// Auditable returns all auditable/loggable parameters +func (r DalSensitivityLevelUpdate) GetHandle() string { + return r.Handle +} + +// Auditable returns all auditable/loggable parameters +func (r DalSensitivityLevelUpdate) GetLevel() int { + return r.Level +} + +// Auditable returns all auditable/loggable parameters +func (r DalSensitivityLevelUpdate) GetMeta() types.DalSensitivityLevelMeta { + return r.Meta +} + +// Fill processes request and fills internal variables +func (r *DalSensitivityLevelUpdate) Fill(req *http.Request) (err error) { + + if strings.HasPrefix(strings.ToLower(req.Header.Get("content-type")), "application/json") { + err = json.NewDecoder(req.Body).Decode(r) + + switch { + case err == io.EOF: + err = nil + case err != nil: + return fmt.Errorf("error parsing http request body: %w", err) + } + } + + { + // Caching 32MB to memory, the rest to disk + if err = req.ParseMultipartForm(32 << 20); err != nil && err != http.ErrNotMultipart { + return err + } else if err == nil { + // Multipart params + + if val, ok := req.MultipartForm.Value["handle"]; ok && len(val) > 0 { + r.Handle, err = val[0], nil + if err != nil { + return err + } + } + + if val, ok := req.MultipartForm.Value["level"]; ok && len(val) > 0 { + r.Level, err = payload.ParseInt(val[0]), nil + if err != nil { + return err + } + } + + if val, ok := req.MultipartForm.Value["meta[]"]; ok { + r.Meta, err = types.ParseDalSensitivityLevelMeta(val) + if err != nil { + return err + } + } else if val, ok := req.MultipartForm.Value["meta"]; ok { + r.Meta, err = types.ParseDalSensitivityLevelMeta(val) + if err != nil { + return err + } + } + } + } + + { + if err = req.ParseForm(); err != nil { + return err + } + + // POST params + + if val, ok := req.Form["handle"]; ok && len(val) > 0 { + r.Handle, err = val[0], nil + if err != nil { + return err + } + } + + if val, ok := req.Form["level"]; ok && len(val) > 0 { + r.Level, err = payload.ParseInt(val[0]), nil + if err != nil { + return err + } + } + + if val, ok := req.Form["meta[]"]; ok { + r.Meta, err = types.ParseDalSensitivityLevelMeta(val) + if err != nil { + return err + } + } else if val, ok := req.Form["meta"]; ok { + r.Meta, err = types.ParseDalSensitivityLevelMeta(val) + if err != nil { + return err + } + } + } + + { + var val string + // path params + + val = chi.URLParam(req, "sensitivityLevelID") + r.SensitivityLevelID, err = payload.ParseUint64(val), nil + if err != nil { + return err + } + + } + + return err +} + +// NewDalSensitivityLevelRead request +func NewDalSensitivityLevelRead() *DalSensitivityLevelRead { + return &DalSensitivityLevelRead{} +} + +// Auditable returns all auditable/loggable parameters +func (r DalSensitivityLevelRead) Auditable() map[string]interface{} { + return map[string]interface{}{ + "sensitivityLevelID": r.SensitivityLevelID, + } +} + +// Auditable returns all auditable/loggable parameters +func (r DalSensitivityLevelRead) GetSensitivityLevelID() uint64 { + return r.SensitivityLevelID +} + +// Fill processes request and fills internal variables +func (r *DalSensitivityLevelRead) Fill(req *http.Request) (err error) { + + { + var val string + // path params + + val = chi.URLParam(req, "sensitivityLevelID") + r.SensitivityLevelID, err = payload.ParseUint64(val), nil + if err != nil { + return err + } + + } + + return err +} + +// NewDalSensitivityLevelDelete request +func NewDalSensitivityLevelDelete() *DalSensitivityLevelDelete { + return &DalSensitivityLevelDelete{} +} + +// Auditable returns all auditable/loggable parameters +func (r DalSensitivityLevelDelete) Auditable() map[string]interface{} { + return map[string]interface{}{ + "sensitivityLevelID": r.SensitivityLevelID, + } +} + +// Auditable returns all auditable/loggable parameters +func (r DalSensitivityLevelDelete) GetSensitivityLevelID() uint64 { + return r.SensitivityLevelID +} + +// Fill processes request and fills internal variables +func (r *DalSensitivityLevelDelete) Fill(req *http.Request) (err error) { + + { + var val string + // path params + + val = chi.URLParam(req, "sensitivityLevelID") + r.SensitivityLevelID, err = payload.ParseUint64(val), nil + if err != nil { + return err + } + + } + + return err +} + +// NewDalSensitivityLevelUndelete request +func NewDalSensitivityLevelUndelete() *DalSensitivityLevelUndelete { + return &DalSensitivityLevelUndelete{} +} + +// Auditable returns all auditable/loggable parameters +func (r DalSensitivityLevelUndelete) Auditable() map[string]interface{} { + return map[string]interface{}{ + "sensitivityLevelID": r.SensitivityLevelID, + } +} + +// Auditable returns all auditable/loggable parameters +func (r DalSensitivityLevelUndelete) GetSensitivityLevelID() uint64 { + return r.SensitivityLevelID +} + +// Fill processes request and fills internal variables +func (r *DalSensitivityLevelUndelete) Fill(req *http.Request) (err error) { + + { + var val string + // path params + + val = chi.URLParam(req, "sensitivityLevelID") + r.SensitivityLevelID, err = payload.ParseUint64(val), nil + if err != nil { + return err + } + + } + + return err +} diff --git a/system/rest/router.go b/system/rest/router.go index 01b030a2c..85f0b6883 100644 --- a/system/rest/router.go +++ b/system/rest/router.go @@ -31,7 +31,9 @@ func MountRoutes() func(r chi.Router) { handlers.NewAuthClient(AuthClient{}.New()).MountRoutes(r) handlers.NewAutomation(Automation{}.New()).MountRoutes(r) handlers.NewUser(User{}.New()).MountRoutes(r) - handlers.NewConnection(Connection{}.New()).MountRoutes(r) + handlers.NewDalConnection(DalConnection{}.New()).MountRoutes(r) + handlers.NewDalSensitivityLevel(SensitivityLevel{}.New()).MountRoutes(r) + handlers.NewDalDriver(DalDriver{}.New()).MountRoutes(r) handlers.NewRole(Role{}.New()).MountRoutes(r) handlers.NewPermissions(Permissions{}.New()).MountRoutes(r) handlers.NewApplication(Application{}.New()).MountRoutes(r) diff --git a/system/rest/sensitivity_level.go b/system/rest/sensitivity_level.go new file mode 100644 index 000000000..8619dbecb --- /dev/null +++ b/system/rest/sensitivity_level.go @@ -0,0 +1,124 @@ +package rest + +import ( + "context" + "io" + "net/http" + "time" + + federationService "github.com/cortezaproject/corteza-server/federation/service" + "github.com/cortezaproject/corteza-server/pkg/api" + "github.com/cortezaproject/corteza-server/pkg/filter" + "github.com/cortezaproject/corteza-server/pkg/payload" + "github.com/cortezaproject/corteza-server/system/rest/request" + "github.com/cortezaproject/corteza-server/system/service" + "github.com/cortezaproject/corteza-server/system/types" + "github.com/pkg/errors" +) + +var _ = errors.Wrap + +type ( + SensitivityLevel struct { + svc sensitivityLevelService + federationSvc federationNodeService + } + + sensitivityLevelSetPayload struct { + Filter types.DalSensitivityLevelFilter `json:"filter"` + Set types.DalSensitivityLevelSet `json:"set"` + } + + sensitivityLevelService interface { + FindByID(ctx context.Context, ID uint64) (*types.DalSensitivityLevel, error) + Create(ctx context.Context, new *types.DalSensitivityLevel) (*types.DalSensitivityLevel, error) + Update(ctx context.Context, upd *types.DalSensitivityLevel) (*types.DalSensitivityLevel, error) + DeleteByID(ctx context.Context, ID uint64) error + UndeleteByID(ctx context.Context, ID uint64) error + Search(ctx context.Context, filter types.DalSensitivityLevelFilter) (types.DalSensitivityLevelSet, types.DalSensitivityLevelFilter, error) + } +) + +func (SensitivityLevel) New() *SensitivityLevel { + return &SensitivityLevel{ + svc: service.DefaultDalSensitivityLevel, + federationSvc: federationService.DefaultNode, + } +} + +func (ctrl SensitivityLevel) List(ctx context.Context, r *request.DalSensitivityLevelList) (interface{}, error) { + var ( + err error + set types.DalSensitivityLevelSet + + f = types.DalSensitivityLevelFilter{ + SensitivityLevelID: payload.ParseUint64s(r.SensitivityLevelID), + + Deleted: filter.State(r.Deleted), + } + ) + + if f.Deleted == 0 { + f.Deleted = filter.StateInclusive + } + + set, f, err = ctrl.svc.Search(ctx, f) + return ctrl.makeFilterPayload(ctx, set, f, err) +} + +func (ctrl SensitivityLevel) Create(ctx context.Context, r *request.DalSensitivityLevelCreate) (interface{}, error) { + sensitivityLevel := &types.DalSensitivityLevel{ + Handle: r.Handle, + Level: r.Level, + Meta: r.Meta, + } + + return ctrl.svc.Create(ctx, sensitivityLevel) +} + +func (ctrl SensitivityLevel) Update(ctx context.Context, r *request.DalSensitivityLevelUpdate) (interface{}, error) { + sensitivityLevel := &types.DalSensitivityLevel{ + ID: r.SensitivityLevelID, + Handle: r.Handle, + Level: r.Level, + Meta: r.Meta, + } + + return ctrl.svc.Update(ctx, sensitivityLevel) +} + +func (ctrl SensitivityLevel) Read(ctx context.Context, r *request.DalSensitivityLevelRead) (interface{}, error) { + return ctrl.svc.FindByID(ctx, r.SensitivityLevelID) +} + +func (ctrl SensitivityLevel) Delete(ctx context.Context, r *request.DalSensitivityLevelDelete) (interface{}, error) { + return api.OK(), ctrl.svc.DeleteByID(ctx, r.SensitivityLevelID) +} + +func (ctrl SensitivityLevel) Undelete(ctx context.Context, r *request.DalSensitivityLevelUndelete) (interface{}, error) { + return api.OK(), ctrl.svc.UndeleteByID(ctx, r.SensitivityLevelID) +} + +func (ctrl SensitivityLevel) makeFilterPayload(ctx context.Context, ll types.DalSensitivityLevelSet, f types.DalSensitivityLevelFilter, err error) (*sensitivityLevelSetPayload, error) { + if err != nil { + return nil, err + } + + if len(ll) == 0 { + ll = make([]*types.DalSensitivityLevel, 0) + } + + return &sensitivityLevelSetPayload{Filter: f, Set: ll}, nil +} + +func (ctrl SensitivityLevel) serve(ctx context.Context, fn string, archive io.ReadSeeker, err error) (interface{}, error) { + if err != nil { + return nil, err + } + + return func(w http.ResponseWriter, req *http.Request) { + w.Header().Add("Content-Disposition", "attachment; filename="+fn) + + http.ServeContent(w, req, fn, time.Now(), archive) + }, nil +} diff --git a/system/service/access_control.gen.go b/system/service/access_control.gen.go index 9e1feb5ff..74c7607de 100644 --- a/system/service/access_control.gen.go +++ b/system/service/access_control.gen.go @@ -329,6 +329,11 @@ func (svc accessControl) List() (out []map[string]string) { "any": types.ComponentRbacResource(), "op": "dal-connections.search", }, + { + "type": types.ComponentResourceType, + "any": types.ComponentRbacResource(), + "op": "dal-sensitivity-level.manage", + }, { "type": types.ComponentResourceType, "any": types.ComponentRbacResource(), @@ -869,6 +874,14 @@ func (svc accessControl) CanSearchDalConnections(ctx context.Context) bool { return svc.can(ctx, "dal-connections.search", r) } +// CanManageDalSensitivityLevel checks if current user can can manage dal sensitivity levels +// +// This function is auto-generated +func (svc accessControl) CanManageDalSensitivityLevel(ctx context.Context) bool { + r := &types.Component{} + return svc.can(ctx, "dal-sensitivity-level.manage", r) +} + // CanCreateApplication checks if current user can create applications // // This function is auto-generated @@ -1006,6 +1019,8 @@ func rbacResourceValidator(r string, oo ...string) error { return rbacUserResourceValidator(r, oo...) case types.DalConnectionResourceType: return rbacDalConnectionResourceValidator(r, oo...) + case types.DalSensitivityLevelResourceType: + return rbacDalSensitivityLevelResourceValidator(r, oo...) case types.ComponentResourceType: return rbacComponentResourceValidator(r, oo...) } @@ -1091,6 +1106,8 @@ func rbacResourceOperations(r string) map[string]bool { "update": true, "delete": true, } + case types.DalSensitivityLevelResourceType: + return map[string]bool{} case types.ComponentResourceType: return map[string]bool{ "grant": true, @@ -1105,6 +1122,7 @@ func rbacResourceOperations(r string) map[string]bool { "users.search": true, "dal-connection.create": true, "dal-connections.search": true, + "dal-sensitivity-level.manage": true, "application.create": true, "applications.search": true, "application.flag.self": true, @@ -1565,6 +1583,50 @@ func rbacDalConnectionResourceValidator(r string, oo ...string) error { return nil } +// rbacDalSensitivityLevelResourceValidator checks validity of RBAC resource and operations +// +// Can be called without operations to check for validity of resource string only +// +// This function is auto-generated +func rbacDalSensitivityLevelResourceValidator(r string, oo ...string) error { + if !strings.HasPrefix(r, types.DalSensitivityLevelResourceType) { + // expecting resource to always include path + return fmt.Errorf("invalid resource type") + } + + defOps := rbacResourceOperations(r) + for _, o := range oo { + if !defOps[o] { + return fmt.Errorf("invalid operation '%s' for dalSensitivityLevel resource", o) + } + } + + const sep = "/" + var ( + pp = strings.Split(strings.Trim(r[len(types.DalSensitivityLevelResourceType):], sep), sep) + prc = []string{ + "ID", + } + ) + + if len(pp) != len(prc) { + return fmt.Errorf("invalid resource path structure") + } + + for i := 0; i < len(pp); i++ { + if pp[i] != "*" { + if i > 0 && pp[i-1] == "*" { + return fmt.Errorf("invalid path wildcard level (%d) for dalSensitivityLevel resource", i) + } + + if _, err := cast.ToUint64E(pp[i]); err != nil { + return fmt.Errorf("invalid reference for %s: '%s'", prc[i], pp[i]) + } + } + } + return nil +} + // rbacComponentResourceValidator checks validity of RBAC resource and operations // // Can be called without operations to check for validity of resource string only diff --git a/system/service/dal_connection.go b/system/service/dal_connection.go index 0c0a87fb6..7b29e76b4 100644 --- a/system/service/dal_connection.go +++ b/system/service/dal_connection.go @@ -33,8 +33,8 @@ type ( } dalConnections interface { - AddConnection(ctx context.Context, connectionID uint64, dsn string, dft dal.ConnectionDefaults, capabilities ...capabilities.Capability) (err error) - UpdateConnection(ctx context.Context, connectionID uint64, dsn string, dft dal.ConnectionDefaults, capabilities ...capabilities.Capability) (err error) + AddConnection(ctx context.Context, connectionID uint64, cp dal.ConnectionParams, dft dal.ConnectionDefaults, capabilities ...capabilities.Capability) (err error) + UpdateConnection(ctx context.Context, connectionID uint64, cp dal.ConnectionParams, dft dal.ConnectionDefaults, capabilities ...capabilities.Capability) (err error) RemoveConnection(ctx context.Context, connectionID uint64) (err error) } ) @@ -84,6 +84,21 @@ func (svc *dalConnection) FindByID(ctx context.Context, ID uint64) (q *types.Dal return q, svc.recordAction(ctx, rProps, DalConnectionActionLookup, err) } +func (svc *dalConnection) FindPrimary(ctx context.Context) (q *types.DalConnection, err error) { + var ( + rProps = &dalConnectionActionProps{} + ) + + err = func() error { + // primary; construct it since it doesn't actually exist + aux := svc.primaryConnection + q = &aux + return nil + }() + + return q, svc.recordAction(ctx, rProps, DalConnectionActionLookup, err) +} + func (svc *dalConnection) Create(ctx context.Context, new *types.DalConnection) (q *types.DalConnection, err error) { var ( qProps = &dalConnectionActionProps{new: new} @@ -104,7 +119,7 @@ func (svc *dalConnection) Create(ctx context.Context, new *types.DalConnection) q = new - return svc.dal.AddConnection(ctx, new.ID, new.DSN, new.ConnectionDefaults(), new.ActiveCapabilities()...) + return svc.dal.AddConnection(ctx, new.ID, new.Config.Connection, new.ConnectionDefaults(), new.ActiveCapabilities()...) }() return q, svc.recordAction(ctx, qProps, DalConnectionActionCreate, err) @@ -136,7 +151,7 @@ func (svc *dalConnection) Update(ctx context.Context, upd *types.DalConnection) q = upd - return svc.dal.UpdateConnection(ctx, upd.ID, upd.DSN, upd.ConnectionDefaults(), upd.ActiveCapabilities()...) + return svc.dal.UpdateConnection(ctx, upd.ID, upd.Config.Connection, upd.ConnectionDefaults(), upd.ActiveCapabilities()...) }() return q, svc.recordAction(ctx, qProps, DalConnectionActionUpdate, err) @@ -204,7 +219,7 @@ func (svc *dalConnection) UndeleteByID(ctx context.Context, ID uint64) (err erro return } - return svc.dal.AddConnection(ctx, q.ID, q.DSN, q.ConnectionDefaults(), q.ActiveCapabilities()...) + return svc.dal.AddConnection(ctx, q.ID, q.Config.Connection, q.ConnectionDefaults(), q.ActiveCapabilities()...) }() return svc.recordAction(ctx, qProps, DalConnectionActionDelete, err) @@ -247,7 +262,7 @@ func (svc *dalConnection) reloadConnections(ctx context.Context) (err error) { } for _, c := range cc { - if err = svc.dal.AddConnection(ctx, c.ID, c.DSN, c.ConnectionDefaults(), c.ActiveCapabilities()...); err != nil { + if err = svc.dal.AddConnection(ctx, c.ID, c.Config.Connection, c.ConnectionDefaults(), c.ActiveCapabilities()...); err != nil { return } } diff --git a/system/service/dal_connection_actions.gen.go b/system/service/dal_connection_actions.gen.go index 4d0638cc1..db972c46f 100644 --- a/system/service/dal_connection_actions.gen.go +++ b/system/service/dal_connection_actions.gen.go @@ -106,15 +106,15 @@ func (p dalConnectionActionProps) Serialize() actionlog.Meta { ) if p.connection != nil { - m.Set("connection.DSN", p.connection.DSN, true) + m.Set("connection.handle", p.connection.Handle, true) m.Set("connection.ID", p.connection.ID, true) } if p.new != nil { - m.Set("new.DSN", p.new.DSN, true) + m.Set("new.handle", p.new.Handle, true) m.Set("new.ID", p.new.ID, true) } if p.update != nil { - m.Set("update.DSN", p.update.DSN, true) + m.Set("update.handle", p.update.Handle, true) m.Set("update.ID", p.update.ID, true) } if p.search != nil { @@ -154,11 +154,11 @@ func (p dalConnectionActionProps) Format(in string, err error) string { pairs, "{{connection}}", fns( - p.connection.DSN, + p.connection.Handle, p.connection.ID, ), ) - pairs = append(pairs, "{{connection.DSN}}", fns(p.connection.DSN)) + pairs = append(pairs, "{{connection.handle}}", fns(p.connection.Handle)) pairs = append(pairs, "{{connection.ID}}", fns(p.connection.ID)) } @@ -168,11 +168,11 @@ func (p dalConnectionActionProps) Format(in string, err error) string { pairs, "{{new}}", fns( - p.new.DSN, + p.new.Handle, p.new.ID, ), ) - pairs = append(pairs, "{{new.DSN}}", fns(p.new.DSN)) + pairs = append(pairs, "{{new.handle}}", fns(p.new.Handle)) pairs = append(pairs, "{{new.ID}}", fns(p.new.ID)) } @@ -182,11 +182,11 @@ func (p dalConnectionActionProps) Format(in string, err error) string { pairs, "{{update}}", fns( - p.update.DSN, + p.update.Handle, p.update.ID, ), ) - pairs = append(pairs, "{{update.DSN}}", fns(p.update.DSN)) + pairs = append(pairs, "{{update.handle}}", fns(p.update.Handle)) pairs = append(pairs, "{{update.ID}}", fns(p.update.ID)) } @@ -619,7 +619,7 @@ func DalConnectionErrNotAllowedToRead(mm ...*dalConnectionActionProps) *errors.E errors.Meta("resource", "system:dal-connection"), // action log entry; no formatting, it will be applied inside recordAction fn. - errors.Meta(dalConnectionLogMetaKey{}, "failed to read {{connection.DSN}}; insufficient permissions"), + errors.Meta(dalConnectionLogMetaKey{}, "failed to read {{connection.handle}}; insufficient permissions"), errors.Meta(dalConnectionPropsMetaKey{}, p), // translation namespace & key @@ -691,7 +691,7 @@ func DalConnectionErrNotAllowedToUpdate(mm ...*dalConnectionActionProps) *errors errors.Meta("resource", "system:dal-connection"), // action log entry; no formatting, it will be applied inside recordAction fn. - errors.Meta(dalConnectionLogMetaKey{}, "failed to update {{connection.DSN}}; insufficient permissions"), + errors.Meta(dalConnectionLogMetaKey{}, "failed to update {{connection.handle}}; insufficient permissions"), errors.Meta(dalConnectionPropsMetaKey{}, p), // translation namespace & key @@ -727,7 +727,7 @@ func DalConnectionErrNotAllowedToDelete(mm ...*dalConnectionActionProps) *errors errors.Meta("resource", "system:dal-connection"), // action log entry; no formatting, it will be applied inside recordAction fn. - errors.Meta(dalConnectionLogMetaKey{}, "failed to delete {{connection.DSN}}; insufficient permissions"), + errors.Meta(dalConnectionLogMetaKey{}, "failed to delete {{connection.handle}}; insufficient permissions"), errors.Meta(dalConnectionPropsMetaKey{}, p), // translation namespace & key @@ -763,7 +763,7 @@ func DalConnectionErrNotAllowedToUndelete(mm ...*dalConnectionActionProps) *erro errors.Meta("resource", "system:dal-connection"), // action log entry; no formatting, it will be applied inside recordAction fn. - errors.Meta(dalConnectionLogMetaKey{}, "failed to undelete {{connection.DSN}}; insufficient permissions"), + errors.Meta(dalConnectionLogMetaKey{}, "failed to undelete {{connection.handle}}; insufficient permissions"), errors.Meta(dalConnectionPropsMetaKey{}, p), // translation namespace & key @@ -799,7 +799,7 @@ func DalConnectionErrNotAllowedToExec(mm ...*dalConnectionActionProps) *errors.E errors.Meta("resource", "system:dal-connection"), // action log entry; no formatting, it will be applied inside recordAction fn. - errors.Meta(dalConnectionLogMetaKey{}, "failed to exec {{connection.DSN}}; insufficient permissions"), + errors.Meta(dalConnectionLogMetaKey{}, "failed to exec {{connection.handle}}; insufficient permissions"), errors.Meta(dalConnectionPropsMetaKey{}, p), // translation namespace & key diff --git a/system/service/dal_connection_actions.yaml b/system/service/dal_connection_actions.yaml index 2e6d4a6a5..dfe743b6e 100644 --- a/system/service/dal_connection_actions.yaml +++ b/system/service/dal_connection_actions.yaml @@ -15,13 +15,13 @@ import: props: - name: connection type: "*types.DalConnection" - fields: [ DSN, ID ] + fields: [ handle, ID ] - name: new type: "*types.DalConnection" - fields: [ DSN, ID ] + fields: [ handle, ID ] - name: update type: "*types.DalConnection" - fields: [ DSN, ID ] + fields: [ handle, ID ] - name: search type: "*types.DalConnectionFilter" fields: [] @@ -74,7 +74,7 @@ errors: - error: notAllowedToRead message: "not allowed to read this connection" - log: "failed to read {{connection.DSN}}; insufficient permissions" + log: "failed to read {{connection.handle}}; insufficient permissions" - error: notAllowedToSearch message: "not allowed to list or search connections" @@ -82,17 +82,17 @@ errors: - error: notAllowedToUpdate message: "not allowed to update this connection" - log: "failed to update {{connection.DSN}}; insufficient permissions" + log: "failed to update {{connection.handle}}; insufficient permissions" - error: notAllowedToDelete message: "not allowed to delete this connection" - log: "failed to delete {{connection.DSN}}; insufficient permissions" + log: "failed to delete {{connection.handle}}; insufficient permissions" - error: notAllowedToUndelete message: "not allowed to undelete this connection" - log: "failed to undelete {{connection.DSN}}; insufficient permissions" + log: "failed to undelete {{connection.handle}}; insufficient permissions" - error: notAllowedToExec message: "not allowed to execute this connection" - log: "failed to exec {{connection.DSN}}; insufficient permissions" + log: "failed to exec {{connection.handle}}; insufficient permissions" diff --git a/system/service/dal_sensitivity_level.go b/system/service/dal_sensitivity_level.go new file mode 100644 index 000000000..2a3a8c831 --- /dev/null +++ b/system/service/dal_sensitivity_level.go @@ -0,0 +1,243 @@ +package service + +import ( + "context" + + "github.com/cortezaproject/corteza-server/pkg/actionlog" + a "github.com/cortezaproject/corteza-server/pkg/auth" + + "github.com/cortezaproject/corteza-server/store" + "github.com/cortezaproject/corteza-server/system/types" +) + +type ( + dalSensitivityLevel struct { + actionlog actionlog.Recorder + store store.Storer + ac sensitivityLevelAccessController + // dal dalSensitivityLevels + } + + sensitivityLevelAccessController interface { + CanManageDalSensitivityLevel(context.Context) bool + } + + // dalSensitivityLevels interface { + // AddSensitivityLevel(ctx context.Context, sensitivityLevelID uint64, cp dal.SensitivityLevelParams, dft dal.SensitivityLevelDefaults, capabilities ...capabilities.Capability) (err error) + // UpdateSensitivityLevel(ctx context.Context, sensitivityLevelID uint64, cp dal.SensitivityLevelParams, dft dal.SensitivityLevelDefaults, capabilities ...capabilities.Capability) (err error) + // RemoveSensitivityLevel(ctx context.Context, sensitivityLevelID uint64) (err error) + // } +) + +func SensitivityLevel(ctx context.Context) (*dalSensitivityLevel, error) { + out := &dalSensitivityLevel{ + ac: DefaultAccessControl, + actionlog: DefaultActionlog, + store: DefaultStore, + // dal: dal, + } + + return out, nil // out.reloadSensitivityLevels(ctx) +} + +func (svc *dalSensitivityLevel) FindByID(ctx context.Context, ID uint64) (q *types.DalSensitivityLevel, err error) { + var ( + rProps = &dalSensitivityLevelActionProps{} + ) + + err = func() error { + if ID == 0 { + return DalSensitivityLevelErrInvalidID() + } + + if q, err = store.LookupDalSensitivityLevelByID(ctx, svc.store, ID); err != nil { + return DalSensitivityLevelErrInvalidID().Wrap(err) + } + + rProps.setSensitivityLevel(q) + + if !svc.ac.CanManageDalSensitivityLevel(ctx) { + return DalSensitivityLevelErrNotAllowedToManage(rProps) + } + + return nil + }() + + return q, svc.recordAction(ctx, rProps, DalSensitivityLevelActionLookup, err) +} + +func (svc *dalSensitivityLevel) Create(ctx context.Context, new *types.DalSensitivityLevel) (q *types.DalSensitivityLevel, err error) { + var ( + qProps = &dalSensitivityLevelActionProps{new: new} + ) + + err = func() (err error) { + if !svc.ac.CanManageDalSensitivityLevel(ctx) { + return DalSensitivityLevelErrNotAllowedToManage(qProps) + } + + new.ID = nextID() + new.CreatedAt = *now() + new.CreatedBy = a.GetIdentityFromContext(ctx).Identity() + + if err = store.CreateDalSensitivityLevel(ctx, svc.store, new); err != nil { + return err + } + + q = new + + // return svc.dal.AddSensitivityLevel(ctx, new.ID, new.Config.SensitivityLevel, new.SensitivityLevelDefaults(), new.ActiveCapabilities()...) + return + }() + + return q, svc.recordAction(ctx, qProps, DalSensitivityLevelActionCreate, err) +} + +func (svc *dalSensitivityLevel) Update(ctx context.Context, upd *types.DalSensitivityLevel) (q *types.DalSensitivityLevel, err error) { + var ( + qProps = &dalSensitivityLevelActionProps{update: upd} + qq *types.DalSensitivityLevel + e error + ) + + err = func() (err error) { + if qq, e = store.LookupDalSensitivityLevelByID(ctx, svc.store, upd.ID); e != nil { + return DalSensitivityLevelErrNotFound(qProps) + } + + if !svc.ac.CanManageDalSensitivityLevel(ctx) { + return DalSensitivityLevelErrNotAllowedToManage(qProps) + } + + upd.UpdatedAt = now() + upd.CreatedAt = qq.CreatedAt + upd.UpdatedBy = a.GetIdentityFromContext(ctx).Identity() + + if err = store.UpdateDalSensitivityLevel(ctx, svc.store, upd); err != nil { + return + } + + q = upd + + // return svc.dal.UpdateSensitivityLevel(ctx, upd.ID, upd.Config.SensitivityLevel, upd.SensitivityLevelDefaults(), upd.ActiveCapabilities()...) + return + }() + + return q, svc.recordAction(ctx, qProps, DalSensitivityLevelActionUpdate, err) +} + +func (svc *dalSensitivityLevel) DeleteByID(ctx context.Context, ID uint64) (err error) { + var ( + qProps = &dalSensitivityLevelActionProps{} + q *types.DalSensitivityLevel + ) + + err = func() (err error) { + if ID == 0 { + return DalSensitivityLevelErrInvalidID() + } + + if q, err = store.LookupDalSensitivityLevelByID(ctx, svc.store, ID); err != nil { + return + } + + if !svc.ac.CanManageDalSensitivityLevel(ctx) { + return DalSensitivityLevelErrNotAllowedToManage(qProps) + } + + qProps.setSensitivityLevel(q) + + q.DeletedAt = now() + q.DeletedBy = a.GetIdentityFromContext(ctx).Identity() + + if err = store.UpdateDalSensitivityLevel(ctx, svc.store, q); err != nil { + return + } + + // return svc.dal.RemoveSensitivityLevel(ctx, q.ID) + return + }() + + return svc.recordAction(ctx, qProps, DalSensitivityLevelActionDelete, err) +} + +func (svc *dalSensitivityLevel) UndeleteByID(ctx context.Context, ID uint64) (err error) { + var ( + qProps = &dalSensitivityLevelActionProps{} + q *types.DalSensitivityLevel + ) + + err = func() (err error) { + if ID == 0 { + return DalSensitivityLevelErrInvalidID() + } + + if q, err = store.LookupDalSensitivityLevelByID(ctx, svc.store, ID); err != nil { + return + } + + if !svc.ac.CanManageDalSensitivityLevel(ctx) { + return DalSensitivityLevelErrNotAllowedToManage(qProps) + } + + qProps.setSensitivityLevel(q) + + q.DeletedAt = nil + q.UpdatedBy = a.GetIdentityFromContext(ctx).Identity() + + if err = store.UpdateDalSensitivityLevel(ctx, svc.store, q); err != nil { + return + } + + // return svc.dal.AddSensitivityLevel(ctx, q.ID, q.Config.SensitivityLevel, q.SensitivityLevelDefaults(), q.ActiveCapabilities()...) + return + }() + + return svc.recordAction(ctx, qProps, DalSensitivityLevelActionDelete, err) +} + +func (svc *dalSensitivityLevel) Search(ctx context.Context, filter types.DalSensitivityLevelFilter) (r types.DalSensitivityLevelSet, f types.DalSensitivityLevelFilter, err error) { + var ( + aProps = &dalSensitivityLevelActionProps{search: &filter} + ) + + // For each fetched item, store backend will check if it is valid or not + filter.Check = func(res *types.DalSensitivityLevel) (bool, error) { + if !svc.ac.CanManageDalSensitivityLevel(ctx) { + return false, nil + } + + return true, nil + } + + err = func() error { + if !svc.ac.CanManageDalSensitivityLevel(ctx) { + return DalSensitivityLevelErrNotAllowedToManage() + } + + if r, f, err = store.SearchDalSensitivityLevels(ctx, svc.store, filter); err != nil { + return err + } + + return nil + }() + + return r, f, svc.recordAction(ctx, aProps, DalSensitivityLevelActionSearch, err) +} + +// func (svc *dalSensitivityLevel) reloadSensitivityLevels(ctx context.Context) (err error) { +// // Get all available sensitivityLevels +// cc, _, err := store.SearchDalSensitivityLevels(ctx, svc.store, types.DalSensitivityLevelFilter{}) +// if err != nil { +// return +// } + +// for _, c := range cc { +// // if err = svc.dal.AddSensitivityLevel(ctx, c.ID, c.Config.SensitivityLevel, c.SensitivityLevelDefaults(), c.ActiveCapabilities()...); err != nil { +// return +// return +// } +// } + +// return +// } diff --git a/system/service/dal_sensitivity_level_actions.gen.go b/system/service/dal_sensitivity_level_actions.gen.go new file mode 100644 index 000000000..a4f142de8 --- /dev/null +++ b/system/service/dal_sensitivity_level_actions.gen.go @@ -0,0 +1,645 @@ +package service + +// This file is auto-generated. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// Definitions file that controls how this file is generated: +// system/service/dal_sensitivity_level_actions.yaml + +import ( + "context" + "fmt" + "github.com/cortezaproject/corteza-server/pkg/actionlog" + "github.com/cortezaproject/corteza-server/pkg/errors" + "github.com/cortezaproject/corteza-server/pkg/locale" + "github.com/cortezaproject/corteza-server/system/types" + "strings" + "time" +) + +type ( + dalSensitivityLevelActionProps struct { + sensitivityLevel *types.DalSensitivityLevel + new *types.DalSensitivityLevel + update *types.DalSensitivityLevel + search *types.DalSensitivityLevelFilter + } + + dalSensitivityLevelAction struct { + timestamp time.Time + resource string + action string + log string + severity actionlog.Severity + + // prefix for error when action fails + errorMessage string + + props *dalSensitivityLevelActionProps + } + + dalSensitivityLevelLogMetaKey struct{} + dalSensitivityLevelPropsMetaKey struct{} +) + +var ( + // just a placeholder to cover template cases w/o fmt package use + _ = fmt.Println +) + +// ********************************************************************************************************************* +// ********************************************************************************************************************* +// Props methods +// setSensitivityLevel updates dalSensitivityLevelActionProps's sensitivityLevel +// +// Allows method chaining +// +// This function is auto-generated. +// +func (p *dalSensitivityLevelActionProps) setSensitivityLevel(sensitivityLevel *types.DalSensitivityLevel) *dalSensitivityLevelActionProps { + p.sensitivityLevel = sensitivityLevel + return p +} + +// setNew updates dalSensitivityLevelActionProps's new +// +// Allows method chaining +// +// This function is auto-generated. +// +func (p *dalSensitivityLevelActionProps) setNew(new *types.DalSensitivityLevel) *dalSensitivityLevelActionProps { + p.new = new + return p +} + +// setUpdate updates dalSensitivityLevelActionProps's update +// +// Allows method chaining +// +// This function is auto-generated. +// +func (p *dalSensitivityLevelActionProps) setUpdate(update *types.DalSensitivityLevel) *dalSensitivityLevelActionProps { + p.update = update + return p +} + +// setSearch updates dalSensitivityLevelActionProps's search +// +// Allows method chaining +// +// This function is auto-generated. +// +func (p *dalSensitivityLevelActionProps) setSearch(search *types.DalSensitivityLevelFilter) *dalSensitivityLevelActionProps { + p.search = search + return p +} + +// Serialize converts dalSensitivityLevelActionProps to actionlog.Meta +// +// This function is auto-generated. +// +func (p dalSensitivityLevelActionProps) Serialize() actionlog.Meta { + var ( + m = make(actionlog.Meta) + ) + + if p.sensitivityLevel != nil { + m.Set("sensitivityLevel.handle", p.sensitivityLevel.Handle, true) + m.Set("sensitivityLevel.ID", p.sensitivityLevel.ID, true) + } + if p.new != nil { + m.Set("new.handle", p.new.Handle, true) + m.Set("new.ID", p.new.ID, true) + } + if p.update != nil { + m.Set("update.handle", p.update.Handle, true) + m.Set("update.ID", p.update.ID, true) + } + if p.search != nil { + } + + return m +} + +// tr translates string and replaces meta value placeholder with values +// +// This function is auto-generated. +// +func (p dalSensitivityLevelActionProps) Format(in string, err error) string { + var ( + pairs = []string{"{{err}}"} + // first non-empty string + fns = func(ii ...interface{}) string { + for _, i := range ii { + if s := fmt.Sprintf("%v", i); len(s) > 0 { + return s + } + } + + return "" + } + ) + + if err != nil { + pairs = append(pairs, err.Error()) + } else { + pairs = append(pairs, "nil") + } + + if p.sensitivityLevel != nil { + // replacement for "{{sensitivityLevel}}" (in order how fields are defined) + pairs = append( + pairs, + "{{sensitivityLevel}}", + fns( + p.sensitivityLevel.Handle, + p.sensitivityLevel.ID, + ), + ) + pairs = append(pairs, "{{sensitivityLevel.handle}}", fns(p.sensitivityLevel.Handle)) + pairs = append(pairs, "{{sensitivityLevel.ID}}", fns(p.sensitivityLevel.ID)) + } + + if p.new != nil { + // replacement for "{{new}}" (in order how fields are defined) + pairs = append( + pairs, + "{{new}}", + fns( + p.new.Handle, + p.new.ID, + ), + ) + pairs = append(pairs, "{{new.handle}}", fns(p.new.Handle)) + pairs = append(pairs, "{{new.ID}}", fns(p.new.ID)) + } + + if p.update != nil { + // replacement for "{{update}}" (in order how fields are defined) + pairs = append( + pairs, + "{{update}}", + fns( + p.update.Handle, + p.update.ID, + ), + ) + pairs = append(pairs, "{{update.handle}}", fns(p.update.Handle)) + pairs = append(pairs, "{{update.ID}}", fns(p.update.ID)) + } + + if p.search != nil { + // replacement for "{{search}}" (in order how fields are defined) + pairs = append( + pairs, + "{{search}}", + fns(), + ) + } + return strings.NewReplacer(pairs...).Replace(in) +} + +// ********************************************************************************************************************* +// ********************************************************************************************************************* +// Action methods + +// String returns loggable description as string +// +// This function is auto-generated. +// +func (a *dalSensitivityLevelAction) String() string { + var props = &dalSensitivityLevelActionProps{} + + if a.props != nil { + props = a.props + } + + return props.Format(a.log, nil) +} + +func (e *dalSensitivityLevelAction) ToAction() *actionlog.Action { + return &actionlog.Action{ + Resource: e.resource, + Action: e.action, + Severity: e.severity, + Description: e.String(), + Meta: e.props.Serialize(), + } +} + +// ********************************************************************************************************************* +// ********************************************************************************************************************* +// Action constructors + +// DalSensitivityLevelActionSearch returns "system:dal-sensitivity-level.search" action +// +// This function is auto-generated. +// +func DalSensitivityLevelActionSearch(props ...*dalSensitivityLevelActionProps) *dalSensitivityLevelAction { + a := &dalSensitivityLevelAction{ + timestamp: time.Now(), + resource: "system:dal-sensitivity-level", + action: "search", + log: "searched for sensitivityLevel", + severity: actionlog.Info, + } + + if len(props) > 0 { + a.props = props[0] + } + + return a +} + +// DalSensitivityLevelActionLookup returns "system:dal-sensitivity-level.lookup" action +// +// This function is auto-generated. +// +func DalSensitivityLevelActionLookup(props ...*dalSensitivityLevelActionProps) *dalSensitivityLevelAction { + a := &dalSensitivityLevelAction{ + timestamp: time.Now(), + resource: "system:dal-sensitivity-level", + action: "lookup", + log: "looked-up for a {{sensitivityLevel}}", + severity: actionlog.Info, + } + + if len(props) > 0 { + a.props = props[0] + } + + return a +} + +// DalSensitivityLevelActionCreate returns "system:dal-sensitivity-level.create" action +// +// This function is auto-generated. +// +func DalSensitivityLevelActionCreate(props ...*dalSensitivityLevelActionProps) *dalSensitivityLevelAction { + a := &dalSensitivityLevelAction{ + timestamp: time.Now(), + resource: "system:dal-sensitivity-level", + action: "create", + log: "created {{sensitivityLevel}}", + severity: actionlog.Notice, + } + + if len(props) > 0 { + a.props = props[0] + } + + return a +} + +// DalSensitivityLevelActionUpdate returns "system:dal-sensitivity-level.update" action +// +// This function is auto-generated. +// +func DalSensitivityLevelActionUpdate(props ...*dalSensitivityLevelActionProps) *dalSensitivityLevelAction { + a := &dalSensitivityLevelAction{ + timestamp: time.Now(), + resource: "system:dal-sensitivity-level", + action: "update", + log: "updated {{sensitivityLevel}}", + severity: actionlog.Notice, + } + + if len(props) > 0 { + a.props = props[0] + } + + return a +} + +// DalSensitivityLevelActionDelete returns "system:dal-sensitivity-level.delete" action +// +// This function is auto-generated. +// +func DalSensitivityLevelActionDelete(props ...*dalSensitivityLevelActionProps) *dalSensitivityLevelAction { + a := &dalSensitivityLevelAction{ + timestamp: time.Now(), + resource: "system:dal-sensitivity-level", + action: "delete", + log: "deleted {{sensitivityLevel}}", + severity: actionlog.Notice, + } + + if len(props) > 0 { + a.props = props[0] + } + + return a +} + +// DalSensitivityLevelActionUndelete returns "system:dal-sensitivity-level.undelete" action +// +// This function is auto-generated. +// +func DalSensitivityLevelActionUndelete(props ...*dalSensitivityLevelActionProps) *dalSensitivityLevelAction { + a := &dalSensitivityLevelAction{ + timestamp: time.Now(), + resource: "system:dal-sensitivity-level", + action: "undelete", + log: "undeleted {{sensitivityLevel}}", + severity: actionlog.Notice, + } + + if len(props) > 0 { + a.props = props[0] + } + + return a +} + +// ********************************************************************************************************************* +// ********************************************************************************************************************* +// Error constructors + +// DalSensitivityLevelErrGeneric returns "system:dal-sensitivity-level.generic" as *errors.Error +// +// +// This function is auto-generated. +// +func DalSensitivityLevelErrGeneric(mm ...*dalSensitivityLevelActionProps) *errors.Error { + var p = &dalSensitivityLevelActionProps{} + if len(mm) > 0 { + p = mm[0] + } + + var e = errors.New( + errors.KindInternal, + + p.Format("failed to complete request due to internal error", nil), + + errors.Meta("type", "generic"), + errors.Meta("resource", "system:dal-sensitivity-level"), + + // action log entry; no formatting, it will be applied inside recordAction fn. + errors.Meta(dalSensitivityLevelLogMetaKey{}, "{err}"), + errors.Meta(dalSensitivityLevelPropsMetaKey{}, p), + + // translation namespace & key + errors.Meta(locale.ErrorMetaNamespace{}, "system"), + errors.Meta(locale.ErrorMetaKey{}, "dalSensitivityLevel.errors.generic"), + + errors.StackSkip(1), + ) + + if len(mm) > 0 { + } + + return e +} + +// DalSensitivityLevelErrNotFound returns "system:dal-sensitivity-level.notFound" as *errors.Error +// +// +// This function is auto-generated. +// +func DalSensitivityLevelErrNotFound(mm ...*dalSensitivityLevelActionProps) *errors.Error { + var p = &dalSensitivityLevelActionProps{} + if len(mm) > 0 { + p = mm[0] + } + + var e = errors.New( + errors.KindInternal, + + p.Format("sensitivityLevel not found", nil), + + errors.Meta("type", "notFound"), + errors.Meta("resource", "system:dal-sensitivity-level"), + + errors.Meta(dalSensitivityLevelPropsMetaKey{}, p), + + // translation namespace & key + errors.Meta(locale.ErrorMetaNamespace{}, "system"), + errors.Meta(locale.ErrorMetaKey{}, "dalSensitivityLevel.errors.notFound"), + + errors.StackSkip(1), + ) + + if len(mm) > 0 { + } + + return e +} + +// DalSensitivityLevelErrInvalidID returns "system:dal-sensitivity-level.invalidID" as *errors.Error +// +// +// This function is auto-generated. +// +func DalSensitivityLevelErrInvalidID(mm ...*dalSensitivityLevelActionProps) *errors.Error { + var p = &dalSensitivityLevelActionProps{} + if len(mm) > 0 { + p = mm[0] + } + + var e = errors.New( + errors.KindInternal, + + p.Format("invalid ID", nil), + + errors.Meta("type", "invalidID"), + errors.Meta("resource", "system:dal-sensitivity-level"), + + errors.Meta(dalSensitivityLevelPropsMetaKey{}, p), + + // translation namespace & key + errors.Meta(locale.ErrorMetaNamespace{}, "system"), + errors.Meta(locale.ErrorMetaKey{}, "dalSensitivityLevel.errors.invalidID"), + + errors.StackSkip(1), + ) + + if len(mm) > 0 { + } + + return e +} + +// DalSensitivityLevelErrInvalidEndpoint returns "system:dal-sensitivity-level.invalidEndpoint" as *errors.Error +// +// +// This function is auto-generated. +// +func DalSensitivityLevelErrInvalidEndpoint(mm ...*dalSensitivityLevelActionProps) *errors.Error { + var p = &dalSensitivityLevelActionProps{} + if len(mm) > 0 { + p = mm[0] + } + + var e = errors.New( + errors.KindInternal, + + p.Format("invalid DSN", nil), + + errors.Meta("type", "invalidEndpoint"), + errors.Meta("resource", "system:dal-sensitivity-level"), + + errors.Meta(dalSensitivityLevelPropsMetaKey{}, p), + + // translation namespace & key + errors.Meta(locale.ErrorMetaNamespace{}, "system"), + errors.Meta(locale.ErrorMetaKey{}, "dalSensitivityLevel.errors.invalidEndpoint"), + + errors.StackSkip(1), + ) + + if len(mm) > 0 { + } + + return e +} + +// DalSensitivityLevelErrExistsEndpoint returns "system:dal-sensitivity-level.existsEndpoint" as *errors.Error +// +// +// This function is auto-generated. +// +func DalSensitivityLevelErrExistsEndpoint(mm ...*dalSensitivityLevelActionProps) *errors.Error { + var p = &dalSensitivityLevelActionProps{} + if len(mm) > 0 { + p = mm[0] + } + + var e = errors.New( + errors.KindInternal, + + p.Format("sensitivityLevel with this DSN already exists", nil), + + errors.Meta("type", "existsEndpoint"), + errors.Meta("resource", "system:dal-sensitivity-level"), + + errors.Meta(dalSensitivityLevelPropsMetaKey{}, p), + + // translation namespace & key + errors.Meta(locale.ErrorMetaNamespace{}, "system"), + errors.Meta(locale.ErrorMetaKey{}, "dalSensitivityLevel.errors.existsEndpoint"), + + errors.StackSkip(1), + ) + + if len(mm) > 0 { + } + + return e +} + +// DalSensitivityLevelErrAlreadyExists returns "system:dal-sensitivity-level.alreadyExists" as *errors.Error +// +// +// This function is auto-generated. +// +func DalSensitivityLevelErrAlreadyExists(mm ...*dalSensitivityLevelActionProps) *errors.Error { + var p = &dalSensitivityLevelActionProps{} + if len(mm) > 0 { + p = mm[0] + } + + var e = errors.New( + errors.KindInternal, + + p.Format("sensitivityLevel by that DSN already exists", nil), + + errors.Meta("type", "alreadyExists"), + errors.Meta("resource", "system:dal-sensitivity-level"), + + errors.Meta(dalSensitivityLevelPropsMetaKey{}, p), + + // translation namespace & key + errors.Meta(locale.ErrorMetaNamespace{}, "system"), + errors.Meta(locale.ErrorMetaKey{}, "dalSensitivityLevel.errors.alreadyExists"), + + errors.StackSkip(1), + ) + + if len(mm) > 0 { + } + + return e +} + +// DalSensitivityLevelErrNotAllowedToManage returns "system:dal-sensitivity-level.notAllowedToManage" as *errors.Error +// +// +// This function is auto-generated. +// +func DalSensitivityLevelErrNotAllowedToManage(mm ...*dalSensitivityLevelActionProps) *errors.Error { + var p = &dalSensitivityLevelActionProps{} + if len(mm) > 0 { + p = mm[0] + } + + var e = errors.New( + errors.KindInternal, + + p.Format("not allowed to Manage a sensitivityLevel", nil), + + errors.Meta("type", "notAllowedToManage"), + errors.Meta("resource", "system:dal-sensitivity-level"), + + // action log entry; no formatting, it will be applied inside recordAction fn. + errors.Meta(dalSensitivityLevelLogMetaKey{}, "failed to Manage a sensitivityLevel; insufficient permissions"), + errors.Meta(dalSensitivityLevelPropsMetaKey{}, p), + + // translation namespace & key + errors.Meta(locale.ErrorMetaNamespace{}, "system"), + errors.Meta(locale.ErrorMetaKey{}, "dalSensitivityLevel.errors.notAllowedToManage"), + + errors.StackSkip(1), + ) + + if len(mm) > 0 { + } + + return e +} + +// ********************************************************************************************************************* +// ********************************************************************************************************************* + +// recordAction is a service helper function wraps function that can return error +// +// It will wrap unrecognized/internal errors with generic errors. +// +// This function is auto-generated. +// +func (svc dalSensitivityLevel) recordAction(ctx context.Context, props *dalSensitivityLevelActionProps, actionFn func(...*dalSensitivityLevelActionProps) *dalSensitivityLevelAction, err error) error { + if svc.actionlog == nil || actionFn == nil { + // action log disabled or no action fn passed, return error as-is + return err + } else if err == nil { + // action completed w/o error, record it + svc.actionlog.Record(ctx, actionFn(props).ToAction()) + return nil + } + + a := actionFn(props).ToAction() + + // Extracting error information and recording it as action + a.Error = err.Error() + + switch c := err.(type) { + case *errors.Error: + m := c.Meta() + + a.Error = err.Error() + a.Severity = actionlog.Severity(m.AsInt("severity")) + a.Description = props.Format(m.AsString(dalSensitivityLevelLogMetaKey{}), err) + + if p, has := m[dalSensitivityLevelPropsMetaKey{}]; has { + a.Meta = p.(*dalSensitivityLevelActionProps).Serialize() + } + + svc.actionlog.Record(ctx, a) + default: + svc.actionlog.Record(ctx, a) + } + + // Original error is passed on + return err +} diff --git a/system/service/dal_sensitivity_level_actions.yaml b/system/service/dal_sensitivity_level_actions.yaml new file mode 100644 index 000000000..5521a62c4 --- /dev/null +++ b/system/service/dal_sensitivity_level_actions.yaml @@ -0,0 +1,73 @@ +# List of loggable service actions + +resource: system:dal-sensitivity-level +service: dalSensitivityLevel + +# Default sensitivity for actions +defaultActionSeverity: notice + +# default severity for errors +defaultErrorSeverity: error + +import: + - github.com/cortezaproject/corteza-server/system/types + +props: + - name: sensitivityLevel + type: "*types.DalSensitivityLevel" + fields: [ handle, ID ] + - name: new + type: "*types.DalSensitivityLevel" + fields: [ handle, ID ] + - name: update + type: "*types.DalSensitivityLevel" + fields: [ handle, ID ] + - name: search + type: "*types.DalSensitivityLevelFilter" + fields: [] + +actions: + - action: search + log: "searched for sensitivityLevel" + severity: info + + - action: lookup + log: "looked-up for a {{sensitivityLevel}}" + severity: info + + - action: create + log: "created {{sensitivityLevel}}" + + - action: update + log: "updated {{sensitivityLevel}}" + + - action: delete + log: "deleted {{sensitivityLevel}}" + + - action: undelete + log: "undeleted {{sensitivityLevel}}" + +errors: + - error: notFound + message: "sensitivityLevel not found" + severity: warning + + - error: invalidID + message: "invalid ID" + severity: warning + + - error: invalidEndpoint + message: "invalid DSN" + severity: warning + + - error: existsEndpoint + message: "sensitivityLevel with this DSN already exists" + severity: warning + + - error: alreadyExists + message: "sensitivityLevel by that DSN already exists" + severity: warning + + - error: notAllowedToManage + message: "not allowed to Manage a sensitivityLevel" + log: "failed to Manage a sensitivityLevel; insufficient permissions" diff --git a/system/service/service.go b/system/service/service.go index 465397d62..2014d5b36 100644 --- a/system/service/service.go +++ b/system/service/service.go @@ -74,7 +74,8 @@ var ( DefaultAuth *auth DefaultAuthClient *authClient DefaultUser *user - DefaultConnection *dalConnection + DefaultDalConnection *dalConnection + DefaultDalSensitivityLevel *dalSensitivityLevel DefaultRole *role DefaultApplication *application DefaultReminder ReminderService @@ -149,7 +150,12 @@ func Initialize(ctx context.Context, log *zap.Logger, s store.Storer, primaryCon DefaultSettings = Settings(ctx, DefaultStore, DefaultLogger, DefaultAccessControl, CurrentSettings) primaryConnectionConfig = primaryConn - DefaultConnection, err = Connection(ctx, primaryConnectionConfig, dal.Service()) + DefaultDalConnection, err = Connection(ctx, primaryConnectionConfig, dal.Service()) + if err != nil { + return + } + + DefaultDalSensitivityLevel, err = SensitivityLevel(ctx) if err != nil { return } diff --git a/system/types/dal_connection.go b/system/types/dal_connection.go index d7c0e3614..7706ed6c9 100644 --- a/system/types/dal_connection.go +++ b/system/types/dal_connection.go @@ -8,18 +8,21 @@ import ( "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/geolocation" "github.com/pkg/errors" ) type ( DalConnection struct { ID uint64 `json:"connectionID,string"` + Name string `json:"name"` Handle string `json:"handle"` - DSN string `json:"dsn"` - Location string `json:"location"` - Ownership string `json:"ownership"` - Sensitive bool `json:"sensitive"` + Type string `json:"type"` + + Location *geolocation.Full `json:"location,omitempty"` + Ownership string `json:"ownership"` + SensitivityLevel uint64 `json:"sensitivityLevel,string"` Config ConnectionConfig `json:"config"` Capabilities ConnectionCapabilities `json:"capabilities"` @@ -46,18 +49,16 @@ type ( DefaultAttributeIdent string `json:"defaultAttributeIdent"` DefaultPartitionFormat string `json:"defaultPartitionFormat"` + + PartitionFormatValidator string `json:"partitionFormatValidator"` + + Connection dal.ConnectionParams `json:"connection"` } DalConnectionFilter struct { ConnectionID []uint64 `json:"connectionID,string"` Handle string `json:"handle"` - DSN string `json:"dsn"` - Location string `json:"location"` - Ownership string `json:"ownership"` - Sensitive string `json:"sensitive"` - - LabeledIDs []uint64 `json:"-"` - Labels map[string]string `json:"labels,omitempty"` + Type string `json:"type"` Deleted filter.State `json:"deleted"` @@ -68,11 +69,15 @@ type ( Check func(*DalConnection) (bool, error) `json:"-"` // Standard helpers for paging and sorting - filter.Sorting filter.Paging } ) +var ( + // Used to identify the primary DAL connection instead of an extra flag + DalPrimaryConnectionResourceType = "corteza::system:primary_dal_connection" +) + func (c DalConnection) ConnectionDefaults() dal.ConnectionDefaults { return dal.ConnectionDefaults{ ModelIdent: c.Config.DefaultModelIdent, diff --git a/system/types/dal_sensitivity_level.go b/system/types/dal_sensitivity_level.go new file mode 100644 index 000000000..a0f531afe --- /dev/null +++ b/system/types/dal_sensitivity_level.go @@ -0,0 +1,77 @@ +package types + +import ( + "database/sql/driver" + "encoding/json" + "time" + + "github.com/cortezaproject/corteza-server/pkg/filter" + "github.com/pkg/errors" +) + +type ( + DalSensitivityLevelMeta struct { + Name string `json:"name"` + Description string `json:"description"` + } + + DalSensitivityLevel struct { + ID uint64 `json:"sensitivityLevelID,string"` + Handle string `json:"handle"` + Level int `json:"level"` + + Meta DalSensitivityLevelMeta `json:"meta"` + + Labels map[string]string `json:"labels,omitempty"` + + CreatedAt time.Time `json:"createdAt,omitempty"` + CreatedBy uint64 `json:"createdBy,string" ` + UpdatedAt *time.Time `json:"updatedAt,omitempty"` + UpdatedBy uint64 `json:"updatedBy,string,omitempty" ` + DeletedAt *time.Time `json:"deletedAt,omitempty"` + DeletedBy uint64 `json:"deletedBy,string,omitempty" ` + } + + DalSensitivityLevelFilter struct { + SensitivityLevelID []uint64 `json:"sensitivityLevelID,string"` + + Deleted filter.State `json:"deleted"` + + // Check fn is called by store backend for each resource found function can + // modify the resource and return false if store should not return it + // + // Store then loads additional resources to satisfy the paging parameters + Check func(*DalSensitivityLevel) (bool, error) `json:"-"` + + // Standard helpers for paging and sorting + filter.Paging + } +) + +func ParseDalSensitivityLevelMeta(ss []string) (m DalSensitivityLevelMeta, err error) { + if len(ss) == 0 { + return + } + + err = json.Unmarshal([]byte(ss[0]), &m) + return +} + +func (nm *DalSensitivityLevelMeta) 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 = DalSensitivityLevelMeta{} + case []uint8: + b := value.([]byte) + if err := json.Unmarshal(b, nm); err != nil { + return errors.Wrapf(err, "cannot scan '%v' into DalSensitivityLevelMeta", string(b)) + } + } + + return nil +} + +func (nm DalSensitivityLevelMeta) Value() (driver.Value, error) { + return json.Marshal(nm) +} diff --git a/system/types/rbac.gen.go b/system/types/rbac.gen.go index 398e98be7..ba41ec4af 100644 --- a/system/types/rbac.gen.go +++ b/system/types/rbac.gen.go @@ -24,17 +24,18 @@ var ( ) const ( - ApplicationResourceType = "corteza::system:application" - ApigwRouteResourceType = "corteza::system:apigw-route" - AuthClientResourceType = "corteza::system:auth-client" - QueueResourceType = "corteza::system:queue" - QueueMessageResourceType = "corteza::system:queue_message" - ReportResourceType = "corteza::system:report" - RoleResourceType = "corteza::system:role" - TemplateResourceType = "corteza::system:template" - UserResourceType = "corteza::system:user" - DalConnectionResourceType = "corteza::system:dal_connection" - ComponentResourceType = "corteza::system" + ApplicationResourceType = "corteza::system:application" + ApigwRouteResourceType = "corteza::system:apigw-route" + AuthClientResourceType = "corteza::system:auth-client" + QueueResourceType = "corteza::system:queue" + QueueMessageResourceType = "corteza::system:queue_message" + ReportResourceType = "corteza::system:report" + RoleResourceType = "corteza::system:role" + TemplateResourceType = "corteza::system:template" + UserResourceType = "corteza::system:user" + DalConnectionResourceType = "corteza::system:dal_connection" + DalSensitivityLevelResourceType = "corteza::system:dal_sensitivity_level" + ComponentResourceType = "corteza::system" ) // RbacResource returns string representation of RBAC resource for Application by calling ApplicationRbacResource fn @@ -337,6 +338,36 @@ func DalConnectionRbacResourceTpl() string { return "%s/%s" } +// RbacResource returns string representation of RBAC resource for DalSensitivityLevel by calling DalSensitivityLevelRbacResource fn +// +// RBAC resource is in the corteza::system:dal_sensitivity_level/... format +// +// This function is auto-generated +func (r DalSensitivityLevel) RbacResource() string { + return DalSensitivityLevelRbacResource(r.ID) +} + +// DalSensitivityLevelRbacResource returns string representation of RBAC resource for DalSensitivityLevel +// +// RBAC resource is in the corteza::system:dal_sensitivity_level/... format +// +// This function is auto-generated +func DalSensitivityLevelRbacResource(id uint64) string { + cpts := []interface{}{DalSensitivityLevelResourceType} + if id != 0 { + cpts = append(cpts, strconv.FormatUint(id, 10)) + } else { + cpts = append(cpts, "*") + } + + return fmt.Sprintf(DalSensitivityLevelRbacResourceTpl(), cpts...) + +} + +func DalSensitivityLevelRbacResourceTpl() string { + return "%s/%s" +} + // RbacResource returns string representation of RBAC resource for Component by calling ComponentRbacResource fn // // RBAC resource is in the corteza::system/... format diff --git a/system/types/type_labels.gen.go b/system/types/type_labels.gen.go index 5f7dccb1b..16ab7cfcc 100644 --- a/system/types/type_labels.gen.go +++ b/system/types/type_labels.gen.go @@ -56,30 +56,6 @@ func (m AuthClient) LabelResourceID() uint64 { return m.ID } -// SetLabel adds new label to label map -func (m *DalConnection) SetLabel(key string, value string) { - if m.Labels == nil { - m.Labels = make(map[string]string) - } - - m.Labels[key] = value -} - -// GetLabels adds new label to label map -func (m DalConnection) GetLabels() map[string]string { - return m.Labels -} - -// GetLabels adds new label to label map -func (DalConnection) LabelResourceKind() string { - return "connection" -} - -// GetLabels adds new label to label map -func (m DalConnection) LabelResourceID() uint64 { - return m.ID -} - // SetLabel adds new label to label map func (m *Report) SetLabel(key string, value string) { if m.Labels == nil { diff --git a/system/types/type_set.gen.go b/system/types/type_set.gen.go index b7e1bd317..9d50c4ce3 100644 --- a/system/types/type_set.gen.go +++ b/system/types/type_set.gen.go @@ -70,6 +70,11 @@ type ( // This type is auto-generated. DalConnectionSet []*DalConnection + // DalSensitivityLevelSet slice of DalSensitivityLevel + // + // This type is auto-generated. + DalSensitivityLevelSet []*DalSensitivityLevel + // QueueSet slice of Queue // // This type is auto-generated. @@ -689,6 +694,62 @@ func (set DalConnectionSet) IDs() (IDs []uint64) { return } +// Walk iterates through every slice item and calls w(DalSensitivityLevel) err +// +// This function is auto-generated. +func (set DalSensitivityLevelSet) Walk(w func(*DalSensitivityLevel) error) (err error) { + for i := range set { + if err = w(set[i]); err != nil { + return + } + } + + return +} + +// Filter iterates through every slice item, calls f(DalSensitivityLevel) (bool, err) and return filtered slice +// +// This function is auto-generated. +func (set DalSensitivityLevelSet) Filter(f func(*DalSensitivityLevel) (bool, error)) (out DalSensitivityLevelSet, err error) { + var ok bool + out = DalSensitivityLevelSet{} + for i := range set { + if ok, err = f(set[i]); err != nil { + return + } else if ok { + out = append(out, set[i]) + } + } + + return +} + +// FindByID finds items from slice by its ID property +// +// This function is auto-generated. +func (set DalSensitivityLevelSet) FindByID(ID uint64) *DalSensitivityLevel { + for i := range set { + if set[i].ID == ID { + return set[i] + } + } + + return nil +} + +// IDs returns a slice of uint64s from all items in the set +// +// This function is auto-generated. +func (set DalSensitivityLevelSet) IDs() (IDs []uint64) { + IDs = make([]uint64, len(set)) + + for i := range set { + IDs[i] = set[i].ID + } + + return +} + // Walk iterates through every slice item and calls w(Queue) err // // This function is auto-generated. diff --git a/system/types/type_set.gen_test.go b/system/types/type_set.gen_test.go index 8d74123f2..f87568185 100644 --- a/system/types/type_set.gen_test.go +++ b/system/types/type_set.gen_test.go @@ -958,6 +958,96 @@ func TestDalConnectionSetIDs(t *testing.T) { } } +func TestDalSensitivityLevelSetWalk(t *testing.T) { + var ( + value = make(DalSensitivityLevelSet, 3) + req = require.New(t) + ) + + // check walk with no errors + { + err := value.Walk(func(*DalSensitivityLevel) error { + return nil + }) + req.NoError(err) + } + + // check walk with error + req.Error(value.Walk(func(*DalSensitivityLevel) error { return fmt.Errorf("walk error") })) +} + +func TestDalSensitivityLevelSetFilter(t *testing.T) { + var ( + value = make(DalSensitivityLevelSet, 3) + req = require.New(t) + ) + + // filter nothing + { + set, err := value.Filter(func(*DalSensitivityLevel) (bool, error) { + return true, nil + }) + req.NoError(err) + req.Equal(len(set), len(value)) + } + + // filter one item + { + found := false + set, err := value.Filter(func(*DalSensitivityLevel) (bool, error) { + if !found { + found = true + return found, nil + } + return false, nil + }) + req.NoError(err) + req.Len(set, 1) + } + + // filter error + { + _, err := value.Filter(func(*DalSensitivityLevel) (bool, error) { + return false, fmt.Errorf("filter error") + }) + req.Error(err) + } +} + +func TestDalSensitivityLevelSetIDs(t *testing.T) { + var ( + value = make(DalSensitivityLevelSet, 3) + req = require.New(t) + ) + + // construct objects + value[0] = new(DalSensitivityLevel) + value[1] = new(DalSensitivityLevel) + value[2] = new(DalSensitivityLevel) + // set ids + value[0].ID = 1 + value[1].ID = 2 + value[2].ID = 3 + + // Find existing + { + val := value.FindByID(2) + req.Equal(uint64(2), val.ID) + } + + // Find non-existing + { + val := value.FindByID(4) + req.Nil(val) + } + + // List IDs from set + { + val := value.IDs() + req.Equal(len(val), len(value)) + } +} + func TestQueueSetWalk(t *testing.T) { var ( value = make(QueueSet, 3) diff --git a/system/types/types.yaml b/system/types/types.yaml index c22e03b67..0fc8703ff 100644 --- a/system/types/types.yaml +++ b/system/types/types.yaml @@ -9,7 +9,7 @@ types: User: labelResourceType: user DalConnection: - labelResourceType: connection + DalSensitivityLevel: Application: labelResourceType: application Role: