Files
orbit/internal/storage/mysql/task_operations.go

80 lines
2.9 KiB
Go

package mysql
import (
"context"
"database/sql"
"errors"
"git.yuntuo.hk/k2safe/orbit/internal/fault"
core "git.yuntuo.hk/k2safe/orbit/model"
"git.yuntuo.hk/k2safe/orbit/platform/auth"
"git.yuntuo.hk/k2safe/orbit/pulse/service"
)
const taskOperationColumns = `id,resource_id,operation_id,actor_id,action,created_at`
func scanTaskOperation(row scanner) (service.TaskOperationSummary, error) {
var v service.TaskOperationSummary
err := row.Scan(&v.ID, &v.TaskID, &v.OperationID, &v.ActorID, &v.Action, &v.CreatedAt)
return v, err
}
func (s *TaskStore) ListTaskOperations(ctx context.Context, t auth.Token, id core.ID, in service.HistoryPageInput) (service.TaskOperationPage, error) {
out := service.TaskOperationPage{Items: []service.TaskOperationSummary{}}
err := s.transaction(ctx, t, "tasks:audit:read", func(tx *sql.Tx, p auth.Permissions) error {
if err := authorizeHistoryTask(ctx, tx, t.NamespaceID, id, p); err != nil {
return err
}
query := `SELECT ` + taskOperationColumns + ` FROM orbit_audit_events WHERE namespace_id=? AND resource_kind='task' AND resource_id=?`
args := []any{t.NamespaceID, id}
if in.Cursor != "" {
c, err := decodeHistoryCursorKind(in.Cursor, t.NamespaceID, id, "", "operations")
if err != nil {
return err
}
query += ` AND (created_at<? OR (created_at=? AND id<?))`
args = append(args, *c.Created, *c.Created, c.ID)
}
query += ` ORDER BY created_at DESC,id DESC LIMIT ?`
args = append(args, in.Limit+1)
rows, err := tx.QueryContext(ctx, query, args...)
if err != nil {
return err
}
defer rows.Close()
for rows.Next() {
v, err := scanTaskOperation(rows)
if err != nil {
return err
}
out.Items = append(out.Items, v)
}
if err := rows.Err(); err != nil {
return err
}
if len(out.Items) > in.Limit {
out.Items = out.Items[:in.Limit]
last := out.Items[len(out.Items)-1]
out.NextCursor, err = encodeHistoryCursor(historyCursor{Version: 1, Kind: "operations", Namespace: t.NamespaceID, Task: id, ID: last.ID, Created: &last.CreatedAt})
}
return err
})
return out, err
}
func (s *TaskStore) GetTaskOperation(ctx context.Context, t auth.Token, id, audit core.ID) (service.TaskOperationView, error) {
var out service.TaskOperationView
err := s.transaction(ctx, t, "tasks:audit:read", func(tx *sql.Tx, p auth.Permissions) error {
if err := authorizeHistoryTask(ctx, tx, t.NamespaceID, id, p); err != nil {
return err
}
var before, after []byte
err := tx.QueryRowContext(ctx, `SELECT `+taskOperationColumns+",reason,COALESCE(evidence_ref,''),`before`,`after` FROM orbit_audit_events WHERE namespace_id=? AND resource_kind='task' AND resource_id=? AND id=?", t.NamespaceID, id, audit).Scan(&out.ID, &out.TaskID, &out.OperationID, &out.ActorID, &out.Action, &out.CreatedAt, &out.Reason, &out.EvidenceRef, &before, &after)
if errors.Is(err, sql.ErrNoRows) {
return fault.NotFound
}
out.Before, out.After = before, after
return err
})
return out, err
}