From 1eb360f43e60bfbb149e6e4e64364c3ad1ad6b15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Toma=C5=BE=20Jerman?= Date: Sun, 4 Jun 2023 09:03:04 +0200 Subject: [PATCH] Hook svc level alteration management to DAL --- server/.env.example | 6 - server/app/boot_levels.go | 5 +- server/app/options/db.cue | 6 +- server/compose/service/dal_interfaces.go | 1 - server/compose/service/module.go | 42 +-- server/compose/types/module.go | 2 +- server/pkg/options/options.gen.go | 6 +- server/store/adapters/rdbms/aux_types.gen.go | 46 ++- server/store/adapters/rdbms/filters.gen.go | 18 +- server/store/adapters/rdbms/queries.gen.go | 98 +++--- server/store/adapters/rdbms/rdbms.gen.go | 4 + server/system/dal_schema_alteration.cue | 27 +- server/system/model/models.gen.go | 46 ++- server/system/rest.yaml | 12 + server/system/rest/dal_schema_alteration.go | 10 + .../rest/handlers/dalSchemaAlteration.go | 38 +++ .../rest/request/dalSchemaAlteration.go | 94 ++++++ server/system/rest/router.go | 1 + server/system/service/dal_connection.go | 12 +- .../system/service/dal_schema_alteration.go | 288 ++++++++++++++---- server/system/service/service.go | 2 +- server/system/types/dal_connection.go | 3 +- server/system/types/dal_schema_ateration.go | 22 +- server/system/types/getters_setters.gen.go | 20 ++ 24 files changed, 627 insertions(+), 182 deletions(-) diff --git a/server/.env.example b/server/.env.example index 264595b245..9028cb93a0 100644 --- a/server/.env.example +++ b/server/.env.example @@ -26,12 +26,6 @@ # Default: sqlite3://file::memory:?cache=shared&mode=memory # DB_DSN=sqlite3://file::memory:?cache=shared&mode=memory -############################################################################### -# Allow for irreversible changes to the database schema such as dropping columns and tables. -# Type: bool -# Default: -# DB_ALLOW_DESTRUCTIVE_SCHEMA_CHANGES= - ############################################################################### ############################################################################### # HTTP Client diff --git a/server/app/boot_levels.go b/server/app/boot_levels.go index cfe1d37393..c494b70a7d 100644 --- a/server/app/boot_levels.go +++ b/server/app/boot_levels.go @@ -23,6 +23,7 @@ import ( apigwTypes "github.com/cortezaproject/corteza/server/pkg/apigw/types" "github.com/cortezaproject/corteza/server/pkg/auth" "github.com/cortezaproject/corteza/server/pkg/corredor" + "github.com/cortezaproject/corteza/server/pkg/dal" "github.com/cortezaproject/corteza/server/pkg/eventbus" "github.com/cortezaproject/corteza/server/pkg/healthcheck" "github.com/cortezaproject/corteza/server/pkg/http" @@ -380,11 +381,13 @@ func (app *CortezaApp) InitServices(ctx context.Context) (err error) { Limit: app.Opt.Limit, Attachment: app.Opt.Attachment, }) - if err != nil { return } + // Add alteration management service the global DAL service + dal.Service().Alterations = service.DefaultDalSchemaAlteration + if app.Opt.Messagebus.Enabled { // initialize all the queue handlers messagebus.Service().Init(ctx, service.DefaultQueue) diff --git a/server/app/options/db.cue b/server/app/options/db.cue index e643566ba4..c77f574404 100644 --- a/server/app/options/db.cue +++ b/server/app/options/db.cue @@ -11,11 +11,7 @@ DB: schema.#optionsGroup & { defaultValue: "sqlite3://file::memory:?cache=shared&mode=memory" description: "Database connection string." } - allow_destructive_schema_changes: { - type: "bool" - defaultGoExpr: "false" - description: "Allow for irreversible changes to the database schema such as dropping columns and tables." - } + } title: "Connection to data store backend" } diff --git a/server/compose/service/dal_interfaces.go b/server/compose/service/dal_interfaces.go index e26c18677e..718875dd90 100644 --- a/server/compose/service/dal_interfaces.go +++ b/server/compose/service/dal_interfaces.go @@ -12,7 +12,6 @@ type ( SearchModels(ctx context.Context) (out dal.ModelSet, err error) ReplaceModel(ctx context.Context, model *dal.Model) (err error) RemoveModel(ctx context.Context, connectionID, ID uint64) (err error) - ReplaceModelAttribute(ctx context.Context, model *dal.Model, diff *dal.ModelDiff, hasRecords bool, trans ...dal.TransformationFunction) (err error) GetConnectionByID(uint64) *dal.ConnectionWrap diff --git a/server/compose/service/module.go b/server/compose/service/module.go index d665600399..78cd80cd39 100644 --- a/server/compose/service/module.go +++ b/server/compose/service/module.go @@ -80,8 +80,7 @@ type ( ReplaceModel(context.Context, *dal.Model) error RemoveModel(ctx context.Context, connectionID, ID uint64) error - ReplaceModelAttribute(ctx context.Context, model *dal.Model, diff *dal.ModelDiff, hasRecords bool, trans ...dal.TransformationFunction) (err error) - SearchModelIssues(ID uint64) []error + SearchModelIssues(ID uint64) []dal.Issue } ) @@ -307,15 +306,9 @@ func (svc module) procDal(m *types.Module) { return } - ii := svc.dal.SearchModelIssues(m.ID) - if len(ii) == 0 { + m.Issues = svc.dal.SearchModelIssues(m.ID) + if len(m.Issues) == 0 { m.Issues = nil - return - } - - m.Issues = make([]string, len(ii)) - for i, err := range ii { - m.Issues[i] = err.Error() } } @@ -336,10 +329,6 @@ func (svc module) Create(ctx context.Context, new *types.Module) (*types.Module, } } - if err != nil { - - } - if ns, err = loadNamespace(ctx, s, new.NamespaceID); err != nil { return err } @@ -633,9 +622,6 @@ func (svc module) updater(ctx context.Context, namespaceID, moduleID uint64, act if err = DalModelReplace(ctx, svc.dal, ns, old, m); err != nil { return err } - if err = dalAttributeReplace(ctx, svc.dal, ns, old, m, hasRecords); err != nil { - return err - } } else { if err = svc.eventbus.WaitFor(ctx, event.ModuleAfterDelete(nil, old, ns)); err != nil { return @@ -1169,28 +1155,6 @@ func DalModelReplace(ctx context.Context, dmm dalModelManager, ns *types.Namespa return } -func dalAttributeReplace(ctx context.Context, dmm dalModelManager, ns *types.Namespace, old, new *types.Module, hasRecords bool) (err error) { - oldModel, err := ModulesToModelSet(dmm, ns, old) - if err != nil { - return - } - newModel, err := ModulesToModelSet(dmm, ns, new) - if err != nil { - return - } - - diff := oldModel[0].Diff(newModel[0]) - - // TODO handle the fact that diff is a list of changes so the same field could be present more than once. - for _, d := range diff { - if err = dmm.ReplaceModelAttribute(ctx, oldModel[0], d, hasRecords); err != nil { - return - } - } - - return -} - // Removes a connection from DAL service func DalModelRemove(ctx context.Context, dmm dalModelManager, mm ...*types.Module) (err error) { for _, m := range mm { diff --git a/server/compose/types/module.go b/server/compose/types/module.go index 50581d9758..8ec430d9c2 100644 --- a/server/compose/types/module.go +++ b/server/compose/types/module.go @@ -32,7 +32,7 @@ type ( Labels map[string]string `json:"labels,omitempty"` - Issues []string `json:"issues,omitempty"` + Issues []dal.Issue `json:"issues,omitempty"` NamespaceID uint64 `json:"namespaceID,string"` diff --git a/server/pkg/options/options.gen.go b/server/pkg/options/options.gen.go index 035a3452b9..e1598f96db 100644 --- a/server/pkg/options/options.gen.go +++ b/server/pkg/options/options.gen.go @@ -14,8 +14,7 @@ import ( type ( DBOpt struct { - DSN string `env:"DB_DSN"` - AllowDestructiveSchemaChanges bool `env:"DB_ALLOW_DESTRUCTIVE_SCHEMA_CHANGES"` + DSN string `env:"DB_DSN"` } HTTPClientOpt struct { @@ -275,8 +274,7 @@ type ( // This function is auto-generated func DB() (o *DBOpt) { o = &DBOpt{ - DSN: "sqlite3://file::memory:?cache=shared&mode=memory", - AllowDestructiveSchemaChanges: false, + DSN: "sqlite3://file::memory:?cache=shared&mode=memory", } // Custom defaults diff --git a/server/store/adapters/rdbms/aux_types.gen.go b/server/store/adapters/rdbms/aux_types.gen.go index 379504f355..546707d36a 100644 --- a/server/store/adapters/rdbms/aux_types.gen.go +++ b/server/store/adapters/rdbms/aux_types.gen.go @@ -353,19 +353,24 @@ type ( // auxDalSchemaAlteration is an auxiliary structure used for transporting to/from RDBMS store auxDalSchemaAlteration struct { - ID uint64 `db:"id"` - BatchID uint64 `db:"batchID"` - DependsOn uint64 `db:"dependsOn"` - Kind string `db:"kind"` - Params *systemType.DalSchemaAlterationParams `db:"params"` - CreatedAt time.Time `db:"created_at"` - UpdatedAt *time.Time `db:"updated_at"` - DeletedAt *time.Time `db:"deleted_at"` - CompletedAt *time.Time `db:"completed_at"` - CreatedBy uint64 `db:"created_by"` - UpdatedBy uint64 `db:"updated_by"` - DeletedBy uint64 `db:"deleted_by"` - CompletedBy uint64 `db:"completed_by"` + ID uint64 `db:"id"` + BatchID uint64 `db:"batchID"` + DependsOn uint64 `db:"dependsOn"` + Resource string `db:"resource"` + ResourceType string `db:"resourceType"` + ConnectionID uint64 `db:"connectionID"` + Kind string `db:"kind"` + Params *systemType.DalSchemaAlterationParams `db:"params"` + CreatedAt time.Time `db:"created_at"` + UpdatedAt *time.Time `db:"updated_at"` + DeletedAt *time.Time `db:"deleted_at"` + CompletedAt *time.Time `db:"completed_at"` + DismissedAt *time.Time `db:"dismissed_at"` + CreatedBy uint64 `db:"created_by"` + UpdatedBy uint64 `db:"updated_by"` + DeletedBy uint64 `db:"deleted_by"` + CompletedBy uint64 `db:"completed_by"` + DismissedBy uint64 `db:"dismissed_by"` } // auxDalSensitivityLevel is an auxiliary structure used for transporting to/from RDBMS store @@ -1875,16 +1880,21 @@ func (aux *auxDalSchemaAlteration) encode(res *systemType.DalSchemaAlteration) ( aux.ID = res.ID aux.BatchID = res.BatchID aux.DependsOn = res.DependsOn + aux.Resource = res.Resource + aux.ResourceType = res.ResourceType + aux.ConnectionID = res.ConnectionID aux.Kind = res.Kind aux.Params = res.Params aux.CreatedAt = res.CreatedAt aux.UpdatedAt = res.UpdatedAt aux.DeletedAt = res.DeletedAt aux.CompletedAt = res.CompletedAt + aux.DismissedAt = res.DismissedAt aux.CreatedBy = res.CreatedBy aux.UpdatedBy = res.UpdatedBy aux.DeletedBy = res.DeletedBy aux.CompletedBy = res.CompletedBy + aux.DismissedBy = res.DismissedBy return } @@ -1896,16 +1906,21 @@ func (aux auxDalSchemaAlteration) decode() (res *systemType.DalSchemaAlteration, res.ID = aux.ID res.BatchID = aux.BatchID res.DependsOn = aux.DependsOn + res.Resource = aux.Resource + res.ResourceType = aux.ResourceType + res.ConnectionID = aux.ConnectionID res.Kind = aux.Kind res.Params = aux.Params res.CreatedAt = aux.CreatedAt res.UpdatedAt = aux.UpdatedAt res.DeletedAt = aux.DeletedAt res.CompletedAt = aux.CompletedAt + res.DismissedAt = aux.DismissedAt res.CreatedBy = aux.CreatedBy res.UpdatedBy = aux.UpdatedBy res.DeletedBy = aux.DeletedBy res.CompletedBy = aux.CompletedBy + res.DismissedBy = aux.DismissedBy return } @@ -1917,16 +1932,21 @@ func (aux *auxDalSchemaAlteration) scan(row scanner) error { &aux.ID, &aux.BatchID, &aux.DependsOn, + &aux.Resource, + &aux.ResourceType, + &aux.ConnectionID, &aux.Kind, &aux.Params, &aux.CreatedAt, &aux.UpdatedAt, &aux.DeletedAt, &aux.CompletedAt, + &aux.DismissedAt, &aux.CreatedBy, &aux.UpdatedBy, &aux.DeletedBy, &aux.CompletedBy, + &aux.DismissedBy, ) } diff --git a/server/store/adapters/rdbms/filters.gen.go b/server/store/adapters/rdbms/filters.gen.go index 79dce7ee96..72ef3dd98d 100644 --- a/server/store/adapters/rdbms/filters.gen.go +++ b/server/store/adapters/rdbms/filters.gen.go @@ -807,12 +807,28 @@ func DalSchemaAlterationFilter(d drivers.Dialect, f systemType.DalSchemaAlterati ee = append(ee, expr) } + if expr := stateNilComparison(d, "completed_at", f.Completed); expr != nil { + ee = append(ee, expr) + } + + if expr := stateNilComparison(d, "dismissed_at", f.Dismissed); expr != nil { + ee = append(ee, expr) + } + if val := strings.TrimSpace(f.Kind); len(val) > 0 { ee = append(ee, goqu.C("kind").Eq(f.Kind)) } + if ss := trimStringSlice(f.Resource); len(ss) > 0 { + ee = append(ee, goqu.C("resource").In(ss)) + } + if len(f.AlterationID) > 0 { - ee = append(ee, goqu.C("alteration_id").In(f.AlterationID)) + ee = append(ee, goqu.C("id").In(f.AlterationID)) + } + + if f.BatchID > 0 { + ee = append(ee, goqu.C("batch_id").Eq(f.BatchID)) } return ee, f, err diff --git a/server/store/adapters/rdbms/queries.gen.go b/server/store/adapters/rdbms/queries.gen.go index 2f8d14507b..36582d467e 100644 --- a/server/store/adapters/rdbms/queries.gen.go +++ b/server/store/adapters/rdbms/queries.gen.go @@ -2438,18 +2438,23 @@ var ( dalSchemaAlterationSelectQuery = func(d goqu.DialectWrapper) *goqu.SelectDataset { return d.Select( "id", - "batchID", - "dependsOn", + "batch_id", + "depends_on", + "resource", + "resource_type", + "connection_id", "kind", "params", "created_at", "updated_at", "deleted_at", "completed_at", + "dismissed_at", "created_by", "updated_by", "deleted_by", "completed_by", + "dismissed_by", ).From(dalSchemaAlterationTable) } @@ -2459,19 +2464,24 @@ var ( dalSchemaAlterationInsertQuery = func(d goqu.DialectWrapper, res *systemType.DalSchemaAlteration) *goqu.InsertDataset { return d.Insert(dalSchemaAlterationTable). Rows(goqu.Record{ - "id": res.ID, - "batchID": res.BatchID, - "dependsOn": res.DependsOn, - "kind": res.Kind, - "params": res.Params, - "created_at": res.CreatedAt, - "updated_at": res.UpdatedAt, - "deleted_at": res.DeletedAt, - "completed_at": res.CompletedAt, - "created_by": res.CreatedBy, - "updated_by": res.UpdatedBy, - "deleted_by": res.DeletedBy, - "completed_by": res.CompletedBy, + "id": res.ID, + "batch_id": res.BatchID, + "depends_on": res.DependsOn, + "resource": res.Resource, + "resource_type": res.ResourceType, + "connection_id": res.ConnectionID, + "kind": res.Kind, + "params": res.Params, + "created_at": res.CreatedAt, + "updated_at": res.UpdatedAt, + "deleted_at": res.DeletedAt, + "completed_at": res.CompletedAt, + "dismissed_at": res.DismissedAt, + "created_by": res.CreatedBy, + "updated_by": res.UpdatedBy, + "deleted_by": res.DeletedBy, + "completed_by": res.CompletedBy, + "dismissed_by": res.DismissedBy, }) } @@ -2485,18 +2495,23 @@ var ( OnConflict( goqu.DoUpdate(target[1:], goqu.Record{ - "batchID": res.BatchID, - "dependsOn": res.DependsOn, - "kind": res.Kind, - "params": res.Params, - "created_at": res.CreatedAt, - "updated_at": res.UpdatedAt, - "deleted_at": res.DeletedAt, - "completed_at": res.CompletedAt, - "created_by": res.CreatedBy, - "updated_by": res.UpdatedBy, - "deleted_by": res.DeletedBy, - "completed_by": res.CompletedBy, + "batch_id": res.BatchID, + "depends_on": res.DependsOn, + "resource": res.Resource, + "resource_type": res.ResourceType, + "connection_id": res.ConnectionID, + "kind": res.Kind, + "params": res.Params, + "created_at": res.CreatedAt, + "updated_at": res.UpdatedAt, + "deleted_at": res.DeletedAt, + "completed_at": res.CompletedAt, + "dismissed_at": res.DismissedAt, + "created_by": res.CreatedBy, + "updated_by": res.UpdatedBy, + "deleted_by": res.DeletedBy, + "completed_by": res.CompletedBy, + "dismissed_by": res.DismissedBy, }, ), ) @@ -2508,18 +2523,23 @@ var ( dalSchemaAlterationUpdateQuery = func(d goqu.DialectWrapper, res *systemType.DalSchemaAlteration) *goqu.UpdateDataset { return d.Update(dalSchemaAlterationTable). Set(goqu.Record{ - "batchID": res.BatchID, - "dependsOn": res.DependsOn, - "kind": res.Kind, - "params": res.Params, - "created_at": res.CreatedAt, - "updated_at": res.UpdatedAt, - "deleted_at": res.DeletedAt, - "completed_at": res.CompletedAt, - "created_by": res.CreatedBy, - "updated_by": res.UpdatedBy, - "deleted_by": res.DeletedBy, - "completed_by": res.CompletedBy, + "batch_id": res.BatchID, + "depends_on": res.DependsOn, + "resource": res.Resource, + "resource_type": res.ResourceType, + "connection_id": res.ConnectionID, + "kind": res.Kind, + "params": res.Params, + "created_at": res.CreatedAt, + "updated_at": res.UpdatedAt, + "deleted_at": res.DeletedAt, + "completed_at": res.CompletedAt, + "dismissed_at": res.DismissedAt, + "created_by": res.CreatedBy, + "updated_by": res.UpdatedBy, + "deleted_by": res.DeletedBy, + "completed_by": res.CompletedBy, + "dismissed_by": res.DismissedBy, }). Where(dalSchemaAlterationPrimaryKeys(res)) } diff --git a/server/store/adapters/rdbms/rdbms.gen.go b/server/store/adapters/rdbms/rdbms.gen.go index dd1767082c..4a8336eda6 100644 --- a/server/store/adapters/rdbms/rdbms.gen.go +++ b/server/store/adapters/rdbms/rdbms.gen.go @@ -11786,6 +11786,8 @@ func (Store) sortableDalSchemaAlterationFields() map[string]string { "createdat": "created_at", "deleted_at": "deleted_at", "deletedat": "deleted_at", + "dismissed_at": "dismissed_at", + "dismissedat": "dismissed_at", "id": "id", "updated_at": "updated_at", "updatedat": "updated_at", @@ -11826,6 +11828,8 @@ func (s *Store) collectDalSchemaAlterationCursorValues(res *systemType.DalSchema return res.DeletedAt case "completedAt": return res.CompletedAt + case "dismissedAt": + return res.DismissedAt } return nil } diff --git a/server/system/dal_schema_alteration.cue b/server/system/dal_schema_alteration.cue index 4e08bba9ce..a7cedbda38 100644 --- a/server/system/dal_schema_alteration.cue +++ b/server/system/dal_schema_alteration.cue @@ -17,12 +17,27 @@ dal_schema_alteration: { id: schema.IdField batchID: { goType: "uint64" + storeIdent: "batch_id" dal: { type: "ID" } } dependsOn: { goType: "uint64" + storeIdent: "depends_on" dal: { type: "Ref", refModelResType: "corteza::system:dal-schema-alteration" } } + resource: { + storeIdent: "resource" + dal: { type: "Text", length: 256 } + } + resourceType: { + storeIdent: "resource_type" + dal: { type: "Text", length: 256 } + } + connectionID: { + goType: "uint64" + storeIdent: "connection_id" + dal: { type: "Ref", refModelResType: "corteza::system:dal-connection" } + } kind: { dal: { type: "Text", length: 256 } @@ -38,10 +53,12 @@ dal_schema_alteration: { updated_at: schema.SortableTimestampNilField deleted_at: schema.SortableTimestampNilField completed_at: schema.SortableTimestampNilField + dismissed_at: schema.SortableTimestampNilField created_by: schema.AttributeUserRef updated_by: schema.AttributeUserRef deleted_by: schema.AttributeUserRef completed_by: schema.AttributeUserRef + dismissed_by: schema.AttributeUserRef } indexes: { @@ -62,15 +79,17 @@ dal_schema_alteration: { filter: { struct: { - alteration_id: {goType: "[]uint64", ident: "alterationID" } - batch_id: {goType: "[]uint64", ident: "batchID" } + resource: {goType: "[]string", ident: "resource" } + alteration_id: {goType: "[]uint64", ident: "alterationID", storeIdent: "id" } + batch_id: {goType: "uint64", ident: "batchID" } kind: {} deleted: {goType: "filter.State", storeIdent: "deleted_at"} completed: {goType: "filter.State", storeIdent: "completed_at"} + dismissed: {goType: "filter.State", storeIdent: "dismissed_at"} } - byValue: ["kind", "alteration_id"] - byNilState: ["deleted"] + byValue: ["kind", "resource", "alteration_id", "batch_id"] + byNilState: ["deleted", "completed", "dismissed"] } store: { diff --git a/server/system/model/models.gen.go b/server/system/model/models.gen.go index db30b3c92c..2b798822be 100644 --- a/server/system/model/models.gen.go +++ b/server/system/model/models.gen.go @@ -1131,7 +1131,7 @@ var DalSchemaAlteration = &dal.Model{ &dal.Attribute{ Ident: "BatchID", Type: &dal.TypeID{}, - Store: &dal.CodecAlias{Ident: "batchID"}, + Store: &dal.CodecAlias{Ident: "batch_id"}, }, &dal.Attribute{ @@ -1142,7 +1142,30 @@ var DalSchemaAlteration = &dal.Model{ ResourceType: "corteza::system:dal-schema-alteration", }, }, - Store: &dal.CodecAlias{Ident: "dependsOn"}, + Store: &dal.CodecAlias{Ident: "depends_on"}, + }, + + &dal.Attribute{ + Ident: "Resource", + Type: &dal.TypeText{Length: 256}, + Store: &dal.CodecAlias{Ident: "resource"}, + }, + + &dal.Attribute{ + Ident: "ResourceType", + Type: &dal.TypeText{Length: 256}, + Store: &dal.CodecAlias{Ident: "resource_type"}, + }, + + &dal.Attribute{ + Ident: "ConnectionID", + Type: &dal.TypeRef{ + RefAttribute: "id", + RefModel: &dal.ModelRef{ + ResourceType: "corteza::system:dal-connection", + }, + }, + Store: &dal.CodecAlias{Ident: "connection_id"}, }, &dal.Attribute{ @@ -1185,6 +1208,12 @@ var DalSchemaAlteration = &dal.Model{ Store: &dal.CodecAlias{Ident: "completed_at"}, }, + &dal.Attribute{ + Ident: "DismissedAt", Sortable: true, + Type: &dal.TypeTimestamp{Nullable: true, Timezone: true, Precision: -1}, + Store: &dal.CodecAlias{Ident: "dismissed_at"}, + }, + &dal.Attribute{ Ident: "CreatedBy", Type: &dal.TypeRef{HasDefault: true, @@ -1236,6 +1265,19 @@ var DalSchemaAlteration = &dal.Model{ }, Store: &dal.CodecAlias{Ident: "completed_by"}, }, + + &dal.Attribute{ + Ident: "DismissedBy", + Type: &dal.TypeRef{HasDefault: true, + DefaultValue: 0, + + RefAttribute: "id", + RefModel: &dal.ModelRef{ + ResourceType: "corteza::system:user", + }, + }, + Store: &dal.CodecAlias{Ident: "dismissed_by"}, + }, }, Indexes: dal.IndexSet{ diff --git a/server/system/rest.yaml b/server/system/rest.yaml index db46ac9473..68197d6cc8 100644 --- a/server/system/rest.yaml +++ b/server/system/rest.yaml @@ -973,6 +973,18 @@ endpoints: parameters: path: [ { type: uint64, name: alterationID, required: true, title: "Alteration ID" } ] + - name: apply + method: POST + title: Apply alterations + path: "/apply" + parameters: + get: [ { type: "[]uint64", name: alterationID, required: true, title: "Alteration ID" } ] + - name: dismiss + method: POST + title: Dismiss alterations + path: "/dismiss" + parameters: + get: [ { type: "[]uint64", name: alterationID, required: true, title: "Alteration ID" } ] - title: Data access layer connections path: "/dal/connections" diff --git a/server/system/rest/dal_schema_alteration.go b/server/system/rest/dal_schema_alteration.go index 41eb79d951..c5b49d0693 100644 --- a/server/system/rest/dal_schema_alteration.go +++ b/server/system/rest/dal_schema_alteration.go @@ -42,6 +42,8 @@ type ( FindByID(ctx context.Context, ID uint64) (*types.DalSchemaAlteration, error) DeleteByID(ctx context.Context, ID uint64) error UndeleteByID(ctx context.Context, ID uint64) error + Apply(context.Context, ...uint64) error + Dismiss(context.Context, ...uint64) error } ) @@ -94,6 +96,14 @@ func (ctrl DalSchemaAlteration) Undelete(ctx context.Context, r *request.DalSche return api.OK(), ctrl.svc.UndeleteByID(ctx, r.AlterationID) } +func (ctrl DalSchemaAlteration) Apply(ctx context.Context, r *request.DalSchemaAlterationApply) (interface{}, error) { + return api.OK(), ctrl.svc.Apply(ctx, r.AlterationID...) +} + +func (ctrl DalSchemaAlteration) Dismiss(ctx context.Context, r *request.DalSchemaAlterationDismiss) (interface{}, error) { + return api.OK(), ctrl.svc.Dismiss(ctx, r.AlterationID...) +} + func (ctrl DalSchemaAlteration) makePayload(ctx context.Context, res *types.DalSchemaAlteration, err error) (*alterationPayload, error) { if err != nil || res == nil { return nil, err diff --git a/server/system/rest/handlers/dalSchemaAlteration.go b/server/system/rest/handlers/dalSchemaAlteration.go index 5ebdb56874..9c5cf96252 100644 --- a/server/system/rest/handlers/dalSchemaAlteration.go +++ b/server/system/rest/handlers/dalSchemaAlteration.go @@ -23,6 +23,8 @@ type ( Read(context.Context, *request.DalSchemaAlterationRead) (interface{}, error) Delete(context.Context, *request.DalSchemaAlterationDelete) (interface{}, error) Undelete(context.Context, *request.DalSchemaAlterationUndelete) (interface{}, error) + Apply(context.Context, *request.DalSchemaAlterationApply) (interface{}, error) + Dismiss(context.Context, *request.DalSchemaAlterationDismiss) (interface{}, error) } // HTTP API interface @@ -31,6 +33,8 @@ type ( Read func(http.ResponseWriter, *http.Request) Delete func(http.ResponseWriter, *http.Request) Undelete func(http.ResponseWriter, *http.Request) + Apply func(http.ResponseWriter, *http.Request) + Dismiss func(http.ResponseWriter, *http.Request) } ) @@ -98,6 +102,38 @@ func NewDalSchemaAlteration(h DalSchemaAlterationAPI) *DalSchemaAlteration { return } + api.Send(w, r, value) + }, + Apply: func(w http.ResponseWriter, r *http.Request) { + defer r.Body.Close() + params := request.NewDalSchemaAlterationApply() + if err := params.Fill(r); err != nil { + api.Send(w, r, err) + return + } + + value, err := h.Apply(r.Context(), params) + if err != nil { + api.Send(w, r, err) + return + } + + api.Send(w, r, value) + }, + Dismiss: func(w http.ResponseWriter, r *http.Request) { + defer r.Body.Close() + params := request.NewDalSchemaAlterationDismiss() + if err := params.Fill(r); err != nil { + api.Send(w, r, err) + return + } + + value, err := h.Dismiss(r.Context(), params) + if err != nil { + api.Send(w, r, err) + return + } + api.Send(w, r, value) }, } @@ -110,5 +146,7 @@ func (h DalSchemaAlteration) MountRoutes(r chi.Router, middlewares ...func(http. r.Get("/dal/schema/alterations/{alterationID}", h.Read) r.Delete("/dal/schema/alterations/{alterationID}", h.Delete) r.Post("/dal/schema/alterations/{alterationID}/undelete", h.Undelete) + r.Post("/dal/schema/alterations/apply", h.Apply) + r.Post("/dal/schema/alterations/dismiss", h.Dismiss) }) } diff --git a/server/system/rest/request/dalSchemaAlteration.go b/server/system/rest/request/dalSchemaAlteration.go index bc18bd62ee..512943b608 100644 --- a/server/system/rest/request/dalSchemaAlteration.go +++ b/server/system/rest/request/dalSchemaAlteration.go @@ -85,6 +85,20 @@ type ( // Alteration ID AlterationID uint64 `json:",string"` } + + DalSchemaAlterationApply struct { + // AlterationID GET parameter + // + // Alteration ID + AlterationID []uint64 + } + + DalSchemaAlterationDismiss struct { + // AlterationID GET parameter + // + // Alteration ID + AlterationID []uint64 + } ) // NewDalSchemaAlterationList request @@ -291,3 +305,83 @@ func (r *DalSchemaAlterationUndelete) Fill(req *http.Request) (err error) { return err } + +// NewDalSchemaAlterationApply request +func NewDalSchemaAlterationApply() *DalSchemaAlterationApply { + return &DalSchemaAlterationApply{} +} + +// Auditable returns all auditable/loggable parameters +func (r DalSchemaAlterationApply) Auditable() map[string]interface{} { + return map[string]interface{}{ + "alterationID": r.AlterationID, + } +} + +// Auditable returns all auditable/loggable parameters +func (r DalSchemaAlterationApply) GetAlterationID() []uint64 { + return r.AlterationID +} + +// Fill processes request and fills internal variables +func (r *DalSchemaAlterationApply) Fill(req *http.Request) (err error) { + + { + // GET params + tmp := req.URL.Query() + + if val, ok := tmp["alterationID[]"]; ok { + r.AlterationID, err = payload.ParseUint64s(val), nil + if err != nil { + return err + } + } else if val, ok := tmp["alterationID"]; ok { + r.AlterationID, err = payload.ParseUint64s(val), nil + if err != nil { + return err + } + } + } + + return err +} + +// NewDalSchemaAlterationDismiss request +func NewDalSchemaAlterationDismiss() *DalSchemaAlterationDismiss { + return &DalSchemaAlterationDismiss{} +} + +// Auditable returns all auditable/loggable parameters +func (r DalSchemaAlterationDismiss) Auditable() map[string]interface{} { + return map[string]interface{}{ + "alterationID": r.AlterationID, + } +} + +// Auditable returns all auditable/loggable parameters +func (r DalSchemaAlterationDismiss) GetAlterationID() []uint64 { + return r.AlterationID +} + +// Fill processes request and fills internal variables +func (r *DalSchemaAlterationDismiss) Fill(req *http.Request) (err error) { + + { + // GET params + tmp := req.URL.Query() + + if val, ok := tmp["alterationID[]"]; ok { + r.AlterationID, err = payload.ParseUint64s(val), nil + if err != nil { + return err + } + } else if val, ok := tmp["alterationID"]; ok { + r.AlterationID, err = payload.ParseUint64s(val), nil + if err != nil { + return err + } + } + } + + return err +} diff --git a/server/system/rest/router.go b/server/system/rest/router.go index 0105eed836..dc5f390bb2 100644 --- a/server/system/rest/router.go +++ b/server/system/rest/router.go @@ -34,6 +34,7 @@ func MountRoutes() func(r chi.Router) { handlers.NewDalConnection(DalConnection{}.New()).MountRoutes(r) handlers.NewDalSensitivityLevel(SensitivityLevel{}.New()).MountRoutes(r) handlers.NewDalDriver(DalDriver{}.New()).MountRoutes(r) + handlers.NewDalSchemaAlteration(DalSchemaAlteration{}.New()).MountRoutes(r) handlers.NewRole(Role{}.New()).MountRoutes(r) handlers.NewPermissions(Permissions{}.New()).MountRoutes(r) handlers.NewApplication(Application{}.New()).MountRoutes(r) diff --git a/server/system/service/dal_connection.go b/server/system/service/dal_connection.go index 07b37ea0da..d04d1bae57 100644 --- a/server/system/service/dal_connection.go +++ b/server/system/service/dal_connection.go @@ -40,7 +40,7 @@ type ( dalConnManager interface { ReplaceConnection(context.Context, *dal.ConnectionWrap, bool) error RemoveConnection(context.Context, uint64) error - SearchConnectionIssues(uint64) []error + SearchConnectionIssues(uint64) []dal.Issue } ) @@ -304,15 +304,9 @@ func (svc *dalConnection) procDal(ctx context.Context, c *types.DalConnection) { return } - ii := svc.dal.SearchConnectionIssues(c.ID) - if len(ii) == 0 { + c.Issues = svc.dal.SearchConnectionIssues(c.ID) + if len(c.Issues) == 0 { c.Issues = nil - return - } - - c.Issues = make([]string, len(ii)) - for i, err := range ii { - c.Issues[i] = err.Error() } } diff --git a/server/system/service/dal_schema_alteration.go b/server/system/service/dal_schema_alteration.go index f1a726e96d..a22e318d6d 100644 --- a/server/system/service/dal_schema_alteration.go +++ b/server/system/service/dal_schema_alteration.go @@ -4,7 +4,11 @@ import ( "context" "github.com/cortezaproject/corteza/server/pkg/actionlog" + intAuth "github.com/cortezaproject/corteza/server/pkg/auth" + "github.com/cortezaproject/corteza/server/pkg/dal" "github.com/cortezaproject/corteza/server/pkg/errors" + "github.com/cortezaproject/corteza/server/pkg/filter" + "github.com/cortezaproject/corteza/server/pkg/id" "github.com/cortezaproject/corteza/server/store" "github.com/cortezaproject/corteza/server/system/types" ) @@ -13,19 +17,25 @@ type ( dalSchemaAlteration struct { actionlog actionlog.Recorder ac dalSchemaAlterationAccessController + dal dalAltManager store store.Storer } + dalAltManager interface { + ApplyAlteration(ctx context.Context, alts ...*dal.Alteration) (errs []error, err error) + } + dalSchemaAlterationAccessController interface { } ) -func DalSchemaAlteration() *dalSchemaAlteration { +func DalSchemaAlteration(dal dalAltManager) *dalSchemaAlteration { return &dalSchemaAlteration{ ac: DefaultAccessControl, store: DefaultStore, actionlog: DefaultActionlog, + dal: dal, } } @@ -141,76 +151,250 @@ func (svc dalSchemaAlteration) UndeleteByID(ctx context.Context, dalSchemaAltera }() return svc.recordAction(ctx, uaProps, DalSchemaAlterationActionUndelete, err) - } -func loadDalSchemaAlteration(ctx context.Context, s store.DalSchemaAlterations, ID uint64) (res *types.DalSchemaAlteration, err error) { - if ID == 0 { - return nil, DalSchemaAlterationErrInvalidID() +// ModelAlterations returns all non deleted, non completed, and non dismissed alterations for the given model +func (svc dalSchemaAlteration) ModelAlterations(ctx context.Context, m *dal.Model) (out []*dal.Alteration, err error) { + // @todo boilerplate code around this + + aux, _, err := store.SearchDalSchemaAlterations(ctx, svc.store, types.DalSchemaAlterationFilter{ + Resource: []string{m.Resource}, + Deleted: filter.StateExcluded, + Completed: filter.StateExcluded, + Dismissed: filter.StateExcluded, + }) + if err != nil { + return nil, err } - if res, err = store.LookupDalSchemaAlterationByID(ctx, s, ID); errors.IsNotFound(err) { - return nil, DalSchemaAlterationErrNotFound() + for _, a := range aux { + t := &dal.Alteration{ + ID: a.ID, + BatchID: a.BatchID, + DependsOn: a.DependsOn, + } + + switch a.Kind { + case "attributeAdd": + t.AttributeAdd = a.Params.AttributeAdd + case "attributeDelete": + t.AttributeDelete = a.Params.AttributeDelete + case "attributeReType": + t.AttributeReType = a.Params.AttributeReType + case "attributeReEncode": + t.AttributeReEncode = a.Params.AttributeReEncode + case "modelAdd": + t.ModelAdd = a.Params.ModelAdd + case "modelDelete": + t.ModelDelete = a.Params.ModelDelete + } + + out = append(out, t) } return } -// // uniqueDalSchemaAlterationCheck verifies dalSchemaAlteration's email, dalSchemaAlterationname and handle -// func uniqueDalSchemaAlterationCheck(ctx context.Context, s store.Storer, u *types.DalSchemaAlteration) (err error) { -// isUnique := func(field string) bool { -// f := types.DalSchemaAlterationFilter{ -// // If dalSchemaAlteration exists and is deleted -- not a dup -// Deleted: filter.StateExcluded, +// @todo we can probably do some diffing here to make it more efficient; it'll do for now +func (svc dalSchemaAlteration) SetAlterations(ctx context.Context, m *dal.Model, stale []*dal.Alteration, aa ...*dal.Alteration) (err error) { + // @todo boilerplate code around this + + return store.Tx(ctx, svc.store, func(ctx context.Context, s store.Storer) (err error) { + // Firstly get rid of the old ones + aux := make([]*types.DalSchemaAlteration, len(stale)) + for i, a := range stale { + aux[i] = &types.DalSchemaAlteration{ + ID: a.ID, + } + } + err = store.DeleteDalSchemaAlteration(ctx, s, aux...) + if err != nil { + return + } + + // Now add the new ones + cvt := make(types.DalSchemaAlterationSet, len(aa)) + n := *now() + u := intAuth.GetIdentityFromContext(ctx).Identity() + for i, a := range aa { + t := &types.DalSchemaAlteration{ + ID: a.ID, + BatchID: a.BatchID, + DependsOn: a.DependsOn, + ConnectionID: a.ConnectionID, + Resource: a.Resource, + ResourceType: a.ResourceType, + + Params: &types.DalSchemaAlterationParams{}, + } + + // @todo we'd need to merge this with the old one probably just to preserve the metadata + t.ID = nextID() + t.CreatedAt = n + t.CreatedBy = u + + switch { + case a.AttributeAdd != nil: + t.Kind = "attributeAdd" + t.Params.AttributeAdd = a.AttributeAdd + + case a.AttributeDelete != nil: + t.Kind = "attributeDelete" + t.Params.AttributeDelete = a.AttributeDelete + + case a.AttributeReType != nil: + t.Kind = "attributeReType" + t.Params.AttributeReType = a.AttributeReType + + case a.AttributeReEncode != nil: + t.Kind = "attributeReEncode" + t.Params.AttributeReEncode = a.AttributeReEncode + + case a.ModelAdd != nil: + t.Kind = "modelAdd" + t.Params.ModelAdd = a.ModelAdd + + case a.ModelDelete != nil: + t.Kind = "modelDelete" + t.Params.ModelDelete = a.ModelDelete + } + + cvt[i] = t + } + + return store.UpsertDalSchemaAlteration(ctx, svc.store, cvt...) + }) +} -// // If dalSchemaAlteration exists and is suspended -- duplicate -// Suspended: filter.StateInclusive, -// } +func (svc dalSchemaAlteration) Apply(ctx context.Context, ids ...uint64) (err error) { + // @todo boilerplate (RBAC and such); we might have special RBAC rules for this; + // originally, we wanted to hook into ComposeModule resource (or any resource that defined a model) + aux, _, err := store.SearchDalSchemaAlterations(ctx, svc.store, types.DalSchemaAlterationFilter{ + AlterationID: id.Strings(ids...), + }) + if err != nil { + return + } -// f.Limit = 1 + aa, err := svc.toPkgAlterations(ctx, svc.appliableAlterations(aux...)...) + if err != nil { + return + } -// switch field { -// case "email": -// if u.Email == "" { -// return true -// } + errors, err := svc.dal.ApplyAlteration(ctx, aa...) + if err != nil { + return + } -// f.Email = u.Email + for i, e := range errors { + if e != nil { + aux[i].Error = e.Error() + } else { + aux[i].CompletedAt = now() + aux[i].CompletedBy = intAuth.GetIdentityFromContext(ctx).Identity() + } + } -// case "dalSchemaAlterationname": -// if u.DalSchemaAlterationname == "" { -// return true -// } + return store.UpdateDalSchemaAlteration(ctx, svc.store, aux...) +} -// f.DalSchemaAlterationname = u.DalSchemaAlterationname -// case "handle": -// if u.Handle == "" { -// return true -// } +func (svc dalSchemaAlteration) Dismiss(ctx context.Context, ids ...uint64) (err error) { + // @todo boilerplate (RBAC and such); we might have special RBAC rules for this; + // originally, we wanted to hook into ComposeModule resource (or any resource that defined a model) -// f.Handle = u.Handle -// } + return store.Tx(ctx, svc.store, func(ctx context.Context, s store.Storer) (err error) { + alt, _, err := store.SearchDalSchemaAlterations(ctx, svc.store, types.DalSchemaAlterationFilter{ + AlterationID: id.Strings(ids...), + }) + if err != nil { + return + } -// set, _, err := store.SearchDalSchemaAlterations(ctx, s, f) -// if err != nil || len(set) > 1 { -// // In case of error or multiple dalSchemaAlterations returned -// return false -// } + alt = svc.appliableAlterations(alt...) -// return len(set) == 0 || set[0].ID == u.ID -// } + for _, a := range alt { + a.Error = "" + a.DismissedAt = now() + a.DismissedBy = intAuth.GetIdentityFromContext(ctx).Identity() + } -// if !isUnique("email") { -// return DalSchemaAlterationErrEmailNotUnique() -// } + return store.UpdateDalSchemaAlteration(ctx, s, alt...) + }) +} -// if !isUnique("dalSchemaAlterationname") { -// return DalSchemaAlterationErrDalSchemaAlterationnameNotUnique() -// } +func (svc dalSchemaAlteration) appliableAlterations(aa ...*types.DalSchemaAlteration) (out types.DalSchemaAlterationSet) { + out = make(types.DalSchemaAlterationSet, 0, len(aa)) -// if !isUnique("handle") { -// return DalSchemaAlterationErrHandleNotUnique() -// } + altIndex := make(map[uint64]*types.DalSchemaAlteration, len(aa)) + for _, a := range aa { + altIndex[a.ID] = a + } -// return nil -// } + for _, a := range aa { + // Already completed + if a.CompletedAt != nil { + continue + } + + // Dismissed for manual thing + if a.DismissedAt != nil { + continue + } + + if a.DependsOn != 0 { + // Check if the dependency is completed or inside of the index + if _, ok := altIndex[a.DependsOn]; !ok { + continue + } + } + + out = append(out, a) + } + + return +} + +func loadDalSchemaAlteration(ctx context.Context, s store.DalSchemaAlterations, ID uint64) (res *types.DalSchemaAlteration, err error) { + if ID == 0 { + return nil, DalSchemaAlterationErrInvalidID() + } + + if res, err = store.LookupDalSchemaAlterationByID(ctx, s, ID); errors.IsNotFound(err) { + return nil, DalSchemaAlterationErrNotFound() + } + + return +} + +func (svc dalSchemaAlteration) toPkgAlterations(ctx context.Context, aa ...*types.DalSchemaAlteration) (out []*dal.Alteration, err error) { + out = make([]*dal.Alteration, len(aa)) + for i, a := range aa { + t := &dal.Alteration{ + ID: a.ID, + BatchID: a.BatchID, + DependsOn: a.DependsOn, + ConnectionID: a.ConnectionID, + Resource: a.Resource, + ResourceType: a.ResourceType, + } + + switch a.Kind { + case "attributeAdd": + t.AttributeAdd = a.Params.AttributeAdd + case "attributeDelete": + t.AttributeDelete = a.Params.AttributeDelete + case "attributeReType": + t.AttributeReType = a.Params.AttributeReType + case "attributeReEncode": + t.AttributeReEncode = a.Params.AttributeReEncode + case "modelAdd": + t.ModelAdd = a.Params.ModelAdd + case "modelDelete": + t.ModelDelete = a.Params.ModelDelete + } + + out[i] = t + } + + return +} diff --git a/server/system/service/service.go b/server/system/service/service.go index ce061e891b..61f902c8a8 100644 --- a/server/system/service/service.go +++ b/server/system/service/service.go @@ -159,7 +159,7 @@ func Initialize(ctx context.Context, log *zap.Logger, s store.Storer, ws websock DefaultDalSensitivityLevel = SensitivityLevel(ctx, dal.Service()) - DefaultDalSchemaAlteration = DalSchemaAlteration() + DefaultDalSchemaAlteration = DalSchemaAlteration(dal.Service()) if DefaultObjectStore == nil { var ( diff --git a/server/system/types/dal_connection.go b/server/system/types/dal_connection.go index 69a2b6b0ea..ceba21145a 100644 --- a/server/system/types/dal_connection.go +++ b/server/system/types/dal_connection.go @@ -5,6 +5,7 @@ import ( "encoding/json" "time" + "github.com/cortezaproject/corteza/server/pkg/dal" "github.com/cortezaproject/corteza/server/pkg/geolocation" "github.com/cortezaproject/corteza/server/pkg/sql" @@ -24,7 +25,7 @@ type ( // use this connection and how it affects their behaviour Config ConnectionConfig `json:"config"` - Issues []string `json:"issues,omitempty"` + Issues []dal.Issue `json:"issues,omitempty"` Labels map[string]string `json:"labels,omitempty"` diff --git a/server/system/types/dal_schema_ateration.go b/server/system/types/dal_schema_ateration.go index 2bc9b4c6ca..b54506e981 100644 --- a/server/system/types/dal_schema_ateration.go +++ b/server/system/types/dal_schema_ateration.go @@ -5,6 +5,7 @@ import ( "encoding/json" "time" + "github.com/cortezaproject/corteza/server/pkg/dal" "github.com/cortezaproject/corteza/server/pkg/sql" "github.com/cortezaproject/corteza/server/pkg/filter" @@ -12,13 +13,18 @@ import ( type ( DalSchemaAlteration struct { - ID uint64 `json:"alterationID,string"` - BatchID uint64 `json:"batchID,string"` - DependsOn uint64 `json:"dependsOn,string"` + ID uint64 `json:"alterationID,string"` + BatchID uint64 `json:"batchID,string"` + DependsOn uint64 `json:"dependsOn,string"` + ConnectionID uint64 `json:"connectionID,string"` + Resource string `json:"resource"` + ResourceType string `json:"resourceType"` Kind string `json:"kind"` Params *DalSchemaAlterationParams `json:"params"` + Error string `json:"error,omitempty"` + CreatedAt time.Time `json:"createdAt,omitempty"` CreatedBy uint64 `json:"createdBy,string" ` UpdatedAt *time.Time `json:"updatedAt,omitempty"` @@ -28,18 +34,28 @@ type ( CompletedAt *time.Time `json:"completedAt,omitempty"` CompletedBy uint64 `json:"completedBy,string,omitempty"` + DismissedAt *time.Time `json:"dismissedAt,omitempty"` + DismissedBy uint64 `json:"dismissedBy,string,omitempty"` } DalSchemaAlterationParams struct { + AttributeAdd *dal.AttributeAdd `json:"attributeAdd,omitempty"` + AttributeDelete *dal.AttributeDelete `json:"attributeDelete,omitempty"` + AttributeReType *dal.AttributeReType `json:"attributeReType,omitempty"` + AttributeReEncode *dal.AttributeReEncode `json:"attributeReEncode,omitempty"` + ModelAdd *dal.ModelAdd `json:"modelAdd,omitempty"` + ModelDelete *dal.ModelDelete `json:"modelDelete,omitempty"` } DalSchemaAlterationFilter struct { AlterationID []string `json:"alterationID"` BatchID uint64 `json:"batchID,string"` Kind string `json:"kind"` + Resource []string `json:"resource"` Deleted filter.State `json:"deleted"` Completed filter.State `json:"completed"` + Dismissed filter.State `json:"dismissed"` // Standard helpers for paging and sorting filter.Sorting diff --git a/server/system/types/getters_setters.gen.go b/server/system/types/getters_setters.gen.go index f364f1b350..8d817b1bf7 100644 --- a/server/system/types/getters_setters.gen.go +++ b/server/system/types/getters_setters.gen.go @@ -834,6 +834,8 @@ func (r *DalSchemaAlteration) GetValue(name string, pos uint) (any, error) { return r.CompletedAt, nil case "completedBy", "CompletedBy": return r.CompletedBy, nil + case "connectionID", "ConnectionID": + return r.ConnectionID, nil case "createdAt", "CreatedAt": return r.CreatedAt, nil case "createdBy", "CreatedBy": @@ -844,10 +846,18 @@ func (r *DalSchemaAlteration) GetValue(name string, pos uint) (any, error) { return r.DeletedBy, nil case "dependsOn", "DependsOn": return r.DependsOn, nil + case "dismissedAt", "DismissedAt": + return r.DismissedAt, nil + case "dismissedBy", "DismissedBy": + return r.DismissedBy, nil case "id", "ID": return r.ID, nil case "kind", "Kind": return r.Kind, nil + case "resource", "Resource": + return r.Resource, nil + case "resourceType", "ResourceType": + return r.ResourceType, nil case "updatedAt", "UpdatedAt": return r.UpdatedAt, nil case "updatedBy", "UpdatedBy": @@ -865,6 +875,8 @@ func (r *DalSchemaAlteration) SetValue(name string, pos uint, value any) (err er return cast2.TimePtr(value, &r.CompletedAt) case "completedBy", "CompletedBy": return cast2.Uint64(value, &r.CompletedBy) + case "connectionID", "ConnectionID": + return cast2.Uint64(value, &r.ConnectionID) case "createdAt", "CreatedAt": return cast2.Time(value, &r.CreatedAt) case "createdBy", "CreatedBy": @@ -875,10 +887,18 @@ func (r *DalSchemaAlteration) SetValue(name string, pos uint, value any) (err er return cast2.Uint64(value, &r.DeletedBy) case "dependsOn", "DependsOn": return cast2.Uint64(value, &r.DependsOn) + case "dismissedAt", "DismissedAt": + return cast2.TimePtr(value, &r.DismissedAt) + case "dismissedBy", "DismissedBy": + return cast2.Uint64(value, &r.DismissedBy) case "id", "ID": return cast2.Uint64(value, &r.ID) case "kind", "Kind": return cast2.String(value, &r.Kind) + case "resource", "Resource": + return cast2.String(value, &r.Resource) + case "resourceType", "ResourceType": + return cast2.String(value, &r.ResourceType) case "updatedAt", "UpdatedAt": return cast2.TimePtr(value, &r.UpdatedAt) case "updatedBy", "UpdatedBy":