diff --git a/internal/server/app_updates.go b/internal/server/app_updates.go index bdb56f5..58bbc30 100644 --- a/internal/server/app_updates.go +++ b/internal/server/app_updates.go @@ -419,7 +419,7 @@ func (s *Server) UpdateAppSettings(ctx context.Context, appPathGlob string, dryR return nil, err } - s.apps.DeleteAppsAudit(ctx, results, "update-settings") // Delete instead of update to avoid having to initialize all the linked apps + s.apps.DeleteAppsAudit(ctx, results, "update_settings") // Delete instead of update to avoid having to initialize all the linked apps // Apps will get reloaded on the next request return ret, nil } diff --git a/internal/server/audit_middleware.go b/internal/server/audit_middleware.go index fb37792..6038b1f 100644 --- a/internal/server/audit_middleware.go +++ b/internal/server/audit_middleware.go @@ -34,19 +34,65 @@ func (s *Server) initAuditDB(connectString string) error { return err } - if _, err := s.auditDB.Exec(`create table IF NOT EXISTS audit (rid text, app_id text, create_time int,` + - `user_id text, event_type text, operation text, target text, status text, detail text)`); err != nil { + if err := s.versionUpgradeAuditDB(); err != nil { return err } - if _, err := s.auditDB.Exec(`create index IF NOT EXISTS idx_rid_audit ON audit (rid, create_time DESC)`); err != nil { - return err + + cleanupTicker := time.NewTicker(5 * time.Minute) + go s.auditCleanup(cleanupTicker) + return nil +} + +const CURRENT_AUDIT_DB_VERSION = 1 + +func (s *Server) versionUpgradeAuditDB() error { + version := 0 + row := s.auditDB.QueryRow("SELECT version, last_upgraded FROM audit_version") + var dt time.Time + row.Scan(&version, &dt) + + if version > CURRENT_AUDIT_DB_VERSION { + return fmt.Errorf("audit DB version is newer than server version, exiting. Server %d, DB %d", CURRENT_AUDIT_DB_VERSION, version) + } + + if version == CURRENT_AUDIT_DB_VERSION { + return nil } - if _, err := s.auditDB.Exec(`create index IF NOT EXISTS idx_misc_audit ON audit (app_id, event_type, operation, target, create_time DESC)`); err != nil { + + ctx := context.Background() + tx, err := s.auditDB.BeginTx(ctx, nil) + if err != nil { return err } + defer tx.Rollback() - cleanupTicker := time.NewTicker(5 * time.Minute) - go s.auditCleanup(cleanupTicker) + if version < 1 { + s.Info().Msg("No audit version, initializing") + + if _, err := tx.ExecContext(ctx, `create table audit_version (version int, last_upgraded datetime)`); err != nil { + return err + } + if _, err := tx.ExecContext(ctx, `insert into audit_version values (1, datetime('now'))`); err != nil { + return err + } + + if _, err := tx.Exec(`create table IF NOT EXISTS audit (rid text, app_id text, create_time int,` + + `user_id text, event_type text, operation text, target text, status text, detail text)`); err != nil { + return err + } + + if _, err := tx.Exec(`create index IF NOT EXISTS idx_rid_audit ON audit (rid, create_time DESC)`); err != nil { + return err + + } + if _, err := tx.Exec(`create index IF NOT EXISTS idx_misc_audit ON audit (app_id, event_type, operation, target, create_time DESC)`); err != nil { + return err + } + } + + if err := tx.Commit(); err != nil { + return err + } return nil } diff --git a/internal/server/clace_plugin.go b/internal/server/clace_plugin.go index 53bed63..102db53 100644 --- a/internal/server/clace_plugin.go +++ b/internal/server/clace_plugin.go @@ -279,7 +279,7 @@ func (c *clacePlugin) ListAuditEvents(thread *starlark.Thread, builtin *starlark v.SetKey(starlark.String("app_name"), starlark.String(appInfo.Name)) v.SetKey(starlark.String("app_path"), starlark.String(appInfo.AppPathDomain.String())) } else { - v.SetKey(starlark.String("app_name"), starlark.String("")) + v.SetKey(starlark.String("app_name"), starlark.String(appId)) v.SetKey(starlark.String("app_path"), starlark.String("")) } v.SetKey(starlark.String("create_time_epoch"), starlark.String(strconv.FormatInt(createTime, 10))) @@ -362,11 +362,11 @@ func getOpList(op string) ([]any, string) { case "reload_apps": opList = []any{"reload_apps", "reload_apps_promote_approve", "reload_apps_approve", "reload_apps_promote"} case "approve_apps": - opList = []any{"approve_apps", "approve_apps_promote"} + opList = []any{"approve_apps", "approve_apps_promote", "reload_apps_promote_approve", "reload_apps_approve"} + case "promote_apps": + opList = []any{"promote_apps", "reload_apps_promote_approve", "reload_apps_promote", "approve_apps_promote", "param_update_promote"} case "update_metadata": opList = []any{"update_metadata", "update_metadata_promote"} - case "update_settings": - opList = []any{"update_settings", "update_settings_promote"} case "param_update": opList = []any{"param_update", "param_update_promote"} // Some infrequent operations like account link are not included in the list for now diff --git a/internal/server/router.go b/internal/server/router.go index c738e6f..afd6f19 100644 --- a/internal/server/router.go +++ b/internal/server/router.go @@ -807,7 +807,7 @@ func (h *Handler) updateAppMetadata(r *http.Request) (any, error) { "metadata": updateAppRequest, } - updateResult, err := h.server.StagedUpdate(r.Context(), appPathGlob, dryRun, promote, h.server.updateMetadataHandler, args, "update-metadata") + updateResult, err := h.server.StagedUpdate(r.Context(), appPathGlob, dryRun, promote, h.server.updateMetadataHandler, args, "update_metadata") return updateResult, err }