package model import ( "encoding/json" "time" ) // Changeset statuses. const ( ChangesetOpen = "open" ChangesetApplied = "applied" ChangesetDiscarded = "discarded" ) // Op is one operation in a changeset, for example "record.create". type Op struct { Seq int `json:"seq"` Kind string `json:"op"` // ID is the object the operation acts on. For create operations it is // allocated when the operation is added, so later operations in the // same changeset can refer to the new object. ID int64 `json:"id,omitempty"` // BaseVersion is the version of the object when the operation was // staged. Applying fails with a conflict if the object has changed // since (0 skips the check). BaseVersion int `json:"base_version,omitempty"` Data json.RawMessage `json:"data,omitempty"` Summary string `json:"summary,omitempty"` AddedAt time.Time `json:"added_at"` } // Changeset is a group of operations applied together. type Changeset struct { ID int64 `json:"id"` Description string `json:"description"` Status string `json:"status"` UserID int64 `json:"user_id"` Username string `json:"username"` Via string `json:"via"` // web, api, cli, import, system Ops []Op `json:"ops"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` AppliedAt *time.Time `json:"applied_at,omitempty"` AppliedBy string `json:"applied_by,omitempty"` Result json.RawMessage `json:"result,omitempty"` Diff string `json:"diff,omitempty"` } // Grant gives access to a kind of resource. Filters narrow it: empty // filters match everything. type Grant struct { Resource string `json:"resource"` // zones, records, views, acls, tsig, options, audit, * Access string `json:"access"` // read or write (write implies read) Zones []string `json:"zones,omitempty"` Views []string `json:"views,omitempty"` Names []string `json:"names,omitempty"` Types []string `json:"types,omitempty"` } // User is a person or service account. type User struct { ID int64 `json:"id"` Username string `json:"username"` PasswordHash string `json:"-"` HasPassword bool `json:"has_password"` Admin bool `json:"admin"` Grants []Grant `json:"grants"` Disabled bool `json:"disabled"` Comment string `json:"comment"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` LastLoginAt *time.Time `json:"last_login_at,omitempty"` } // Token is an API key. The secret is shown once at creation and only its // hash is stored. type Token struct { ID int64 `json:"id"` UserID int64 `json:"user_id"` Username string `json:"username,omitempty"` Name string `json:"name"` PublicID string `json:"public_id"` SecretHash string `json:"-"` // Grants restrict the token to a subset of its user's permissions; // nil means the token has all of the user's permissions. Grants []Grant `json:"grants"` ExpiresAt *time.Time `json:"expires_at,omitempty"` CreatedAt time.Time `json:"created_at"` LastUsedAt *time.Time `json:"last_used_at,omitempty"` LastUsedIP string `json:"last_used_ip,omitempty"` RevokedAt *time.Time `json:"revoked_at,omitempty"` // RotatedAt is when the token last got a new secret (nil: never). RotatedAt *time.Time `json:"rotated_at,omitempty"` // After a rotation with a grace period, the previous secret keeps // working until PrevExpiresAt. PrevSecretHash string `json:"-"` PrevExpiresAt *time.Time `json:"previous_secret_valid_until,omitempty"` } // IssuedAt is when the token's current secret was made. func (t *Token) IssuedAt() time.Time { if t.RotatedAt != nil { return *t.RotatedAt } return t.CreatedAt } // Session is a logged-in web session. type Session struct { IDHash string `json:"-"` UserID int64 `json:"user_id"` CSRFToken string `json:"-"` CreatedAt time.Time `json:"created_at"` ExpiresAt time.Time `json:"expires_at"` LastSeenAt time.Time `json:"last_seen_at"` IP string `json:"ip"` UserAgent string `json:"user_agent"` } // AuditEvent records an action. type AuditEvent struct { ID int64 `json:"id"` Time time.Time `json:"time"` UserID int64 `json:"user_id,omitempty"` Username string `json:"username,omitempty"` Auth string `json:"auth,omitempty"` // session, token, local TokenID int64 `json:"token_id,omitempty"` TokenName string `json:"token_name,omitempty"` IP string `json:"ip,omitempty"` UserAgent string `json:"user_agent,omitempty"` Action string `json:"action"` ObjectType string `json:"object_type,omitempty"` ObjectID int64 `json:"object_id,omitempty"` ObjectName string `json:"object_name,omitempty"` ChangesetID int64 `json:"changeset_id,omitempty"` Outcome string `json:"outcome"` // success, failure, denied Message string `json:"message,omitempty"` Details json.RawMessage `json:"details,omitempty"` } // DeployedFile records a file Jarl wrote, for drift detection. type DeployedFile struct { Path string `json:"path"` SHA256 string `json:"sha256"` Size int64 `json:"size"` Kind string `json:"kind"` WrittenAt time.Time `json:"written_at"` ChangesetID int64 `json:"changeset_id"` }