// Package api defines the JSON types of Jarl's HTTP API, shared by the // server and the Go client used by the CLI. package api import ( "encoding/json" "time" "jarl/internal/model" ) // Version is the API path prefix. const Prefix = "/api/v1" // Zone is a zone as returned by the API. type Zone struct { model.Zone Display string `json:"display_name"` View string `json:"view,omitempty"` Records int `json:"record_count"` ZoneFile string `json:"zone_file,omitempty"` // the file named loads RName string `json:"rname_email,omitempty"` // Pending is set when listing with a changeset: add, change or delete. Pending string `json:"pending,omitempty"` } // Record is a record as returned by the API. type Record struct { model.Record Zone string `json:"zone"` View string `json:"view,omitempty"` RelativeName string `json:"relative_name"` EffectiveTTL uint32 `json:"effective_ttl"` // Text is the decoded value of TXT and SPF records. Text *string `json:"text,omitempty"` // Pending is set when listing with a changeset: add, change or delete. Pending string `json:"pending,omitempty"` } // View is a view with its zone count. type View struct { model.View Zones int `json:"zone_count"` } // ACL is an ACL with the objects that use it. type ACL struct { model.ACL UsedBy []string `json:"used_by"` } // TSIGKey is a key; Secret is only filled when asked for and allowed. type TSIGKey struct { model.TSIGKey UsedBy []string `json:"used_by"` } // Option is an option with display helpers. type Option struct { model.Option Where string `json:"where"` // e.g. "view internal" Description string `json:"description,omitempty"` Status string `json:"status,omitempty"` } // User is a user with formatted grants. type User struct { model.User GrantStrings []string `json:"grant_strings"` } // Token is an API token. Secret is only set when the token is created. type Token struct { model.Token GrantStrings []string `json:"grant_strings,omitempty"` Secret string `json:"token,omitempty"` } // Whoami describes the authenticated principal. type Whoami struct { User User `json:"user"` Method string `json:"method"` Token *Token `json:"token,omitempty"` CSRFToken string `json:"csrf_token,omitempty"` Permissions []string `json:"permissions"` Admin bool `json:"admin"` Version string `json:"version"` } // LoginRequest logs in. type LoginRequest struct { Username string `json:"username"` Password string `json:"password"` } // ErrorBody is the error response. type ErrorBody struct { Error ErrorInfo `json:"error"` } // ErrorInfo describes an error. type ErrorInfo struct { Code string `json:"code"` Message string `json:"message"` Op int `json:"op,omitempty"` Problems json.RawMessage `json:"problems,omitempty"` Check json.RawMessage `json:"check,omitempty"` Result json.RawMessage `json:"result,omitempty"` } // ChangeRequest is a request in a batch (POST /apply or changeset ops). type ChangeRequest struct { Op string `json:"op"` ID int64 `json:"id,omitempty"` BaseVersion int `json:"base_version,omitempty"` Data json.RawMessage `json:"data,omitempty"` } // BatchRequest applies (or stages) several requests at once. type BatchRequest struct { Description string `json:"description,omitempty"` Ops []ChangeRequest `json:"ops"` DryRun bool `json:"dry_run,omitempty"` Force bool `json:"force,omitempty"` // Apply (for POST /changesets) applies the new changeset at once. Apply bool `json:"apply,omitempty"` } // MutationResponse is returned by endpoints that change the configuration. type MutationResponse struct { Applied bool `json:"applied"` Staged bool `json:"staged,omitempty"` DryRun bool `json:"dry_run,omitempty"` ChangesetID int64 `json:"changeset_id,omitempty"` Result json.RawMessage `json:"result,omitempty"` Changeset json.RawMessage `json:"changeset,omitempty"` Added []model.Op `json:"added,omitempty"` Warnings []string `json:"warnings,omitempty"` Problems json.RawMessage `json:"problems,omitempty"` Object json.RawMessage `json:"object,omitempty"` } // Changeset is a changeset as returned by the API. type Changeset struct { model.Changeset Undoable bool `json:"undoable"` } // StatusResponse is GET /status. type StatusResponse struct { Version string `json:"version"` Engine json.RawMessage `json:"engine"` Time time.Time `json:"time"` } // SearchResult is one search hit. type SearchResult struct { Kind string `json:"kind"` // zone, record, acl, view, key ID int64 `json:"id"` ZoneID int64 `json:"zone_id,omitempty"` Label string `json:"label"` Detail string `json:"detail,omitempty"` } // PasswordChange changes a password. type PasswordChange struct { Current string `json:"current_password,omitempty"` Password string `json:"password"` } // UserInput creates or updates a user. type UserInput struct { Username *string `json:"username,omitempty"` Password *string `json:"password,omitempty"` Admin *bool `json:"admin,omitempty"` Grants *[]model.Grant `json:"grants,omitempty"` // GrantStrings are grants in compact form ("records:write zones=x"). GrantStrings *[]string `json:"grant_strings,omitempty"` Role *string `json:"role,omitempty"` // a role template name Disabled *bool `json:"disabled,omitempty"` Comment *string `json:"comment,omitempty"` } // TokenInput creates a token. type TokenInput struct { Name string `json:"name"` Grants *[]model.Grant `json:"grants,omitempty"` GrantStrings *[]string `json:"grant_strings,omitempty"` Role string `json:"role,omitempty"` ExpiresIn string `json:"expires_in,omitempty"` // e.g. "90d", "720h" ExpiresAt *time.Time `json:"expires_at,omitempty"` } // ZoneImport imports zone file text into a zone. type ZoneImport struct { Text string `json:"text"` // Mode "merge" adds missing records; "replace" makes the zone equal // to the file (deleting other records). Mode string `json:"mode"` DryRun bool `json:"dry_run,omitempty"` // UseSOA also takes the SOA timers and default TTL from the file. UseSOA bool `json:"use_soa,omitempty"` }