Documentation
¶
Overview ¶
Package admin is Gombit's runtime generic admin (ADMIN-1 through ADMIN-3 / ADR-013).
Feature packages register models explicitly:
admin.Register(app, Product{}, admin.Options{Slug: "products", ...})
framework.New mounts the Huma introspection and data-plane routes, and the /admin/ SPA, only when cookie session auth is on (cfg.Auth.Mode == cookie). JWT-only apps do not get admin routes. Admin requests enforce the registered permission keys; auth.User.IsSuperuser bypasses those checks.
Options is the source of truth. After Register returns, handlers read stored values and GORM constructors — they do not reflect over arbitrary Go types. FieldsFrom and the empty-Fields default may use reflect only inside Register; both are registration-time conveniences.
Index ¶
Constants ¶
const ( RelBelongsTo = string(field.RelBelongsTo) RelHasMany = string(field.RelHasMany) RelManyToMany = string(field.RelManyToMany) RelOneToOne = string(field.RelOneToOne) )
Relation kinds for v1. Defined in package field.
const ( ImplicitCreatedAt = "created_at" ImplicitUpdatedAt = "updated_at" )
Implicit timestamp names allowed in List and Ordering even when omitted from Fields. They are GORM's default created_at / updated_at columns.
Variables ¶
This section is empty.
Functions ¶
func Mount ¶
Mount registers the admin Huma routes on host.API() when cookie auth is on. The catalog is empty until Register is called. framework.New calls Mount automatically in cookie mode; JWT-only apps must not call it.
func Register ¶
Register adds model T to the host's admin registry.
host is typically *framework.App. Missing or duplicate Slug is an error. Cookie auth must already be on (framework.New mounts the empty admin routes in that mode). After Register returns, the registry holds concrete Options values plus constructors for T; request handlers do not walk arbitrary Go types.
Types ¶
type Actions ¶
type Actions struct {
List bool `json:"list"`
Detail bool `json:"detail"`
Create bool `json:"create"`
Update bool `json:"update"`
Delete bool `json:"delete"`
}
Actions names which data-plane operations are enabled for a model.
type Capabilities ¶
type Capabilities struct {
View bool `json:"view"`
Create bool `json:"create"`
Update bool `json:"update"`
Delete bool `json:"delete"`
}
Capabilities are the current user's enabled actions for one model.
type Catalog ¶
type Catalog struct {
Models []ModelMeta `json:"models"`
}
Catalog is the GET /admin/meta success data object.
type CatalogAux ¶
type CatalogAux struct {
Auth *AuthMeta `json:"auth,omitempty"`
}
CatalogAux is optional envelope meta on the catalog.
type Choice ¶ added in v0.3.0
Choice is one enum entry: the stored value and the label the admin shows.
type Field ¶
type Field struct {
Name string `json:"name"`
Type FieldType `json:"type"`
Required bool `json:"required"`
ReadOnly bool `json:"readonly"`
Related *Relation `json:"related,omitempty"`
// Constraints copied from the model's validate tag when the registrar
// leaves them empty. Strings so a decimal bound survives JSON.
Minimum string `json:"minimum,omitempty"`
Maximum string `json:"maximum,omitempty"`
MaxLength int `json:"max_length,omitempty"`
Pattern string `json:"pattern,omitempty"`
// TagPattern is the pattern struct tag, kept apart from a validate
// regex. make resource writes the slug alphabet here. A user regex
// does not change the catalog kind.
TagPattern string `json:"-"`
Default string `json:"default,omitempty"`
// Format is the OpenAPI format from the model tag (email, uri, ip, time,
// duration). The admin wire for email stays string; time and duration
// have their own wires. Writes reject a value that fails the format.
Format string `json:"format,omitempty"`
// Choices are the stored value and display label of an enum. Empty
// when the column is not an enum.
Choices []Choice `json:"choices,omitempty"`
// Column is the GORM/SQL column name. Empty means Name == JSON key ==
// column (the v1 default). When set, it alone picks the model field the
// admin reads and writes (Name is then only the JSON key); a column the
// model does not have is a registration error. Not emitted in meta.
Column string `json:"-"`
// WriteOnly matches a public create field that is omitted from the
// response (`gombit:"write"`). Row payloads leave it out. An update
// applies it only when the body contains a new value.
WriteOnly bool `json:"writeonly,omitempty"`
// Accept and MaxBytes are a file or image field's upload policy (the
// model's storage tag): the media types it accepts and its largest
// file. Set at registration; the admin form uses them as hints, and
// the server enforces them.
Accept []string `json:"accept,omitempty"`
MaxBytes int64 `json:"max_bytes,omitempty"`
// contains filtered or unexported fields
}
Field describes one registered admin field.
Name is the JSON object key used in meta and in data-plane row payloads. For v1, Name is also the GORM/SQL column unless Column is set (when the Go exported name or GORM column differs from the JSON key).
func FieldsFrom ¶
FieldsFrom derives a default []Field from model at registration time. It may use reflect on this one type. Do not call it from request handlers.
Name comes from the json tag when present, otherwise the GORM column / snake_case of the exported field name. Type is inferred from the Go type. Read, write, and hidden follow resourcepolicy — the same gombit tag the generated API uses — so a column cannot be secret on the public contract and editable here. An auto-increment primary key and GORM timestamps stay read-only. A manual primary key stays in the create request and is required; update rejects a different key. GORM created_at / updated_at are included when the policy leaves them on the response.
type FieldMeta ¶
type FieldMeta struct {
Name string `json:"name"`
Type FieldType `json:"type"`
Required bool `json:"required"`
ReadOnly bool `json:"readonly"`
// WriteOnly is a create field the response omits (`gombit:"write"`).
// The edit form leaves the key out until the operator sets a value.
WriteOnly bool `json:"writeonly,omitempty"`
Related *Relation `json:"related,omitempty"`
Minimum string `json:"minimum,omitempty"`
Maximum string `json:"maximum,omitempty"`
MaxLength int `json:"max_length,omitempty"`
Pattern string `json:"pattern,omitempty"`
Default string `json:"default,omitempty"`
Format string `json:"format,omitempty"`
Choices []Choice `json:"choices,omitempty"`
// Accept and MaxBytes: a file or image field's upload policy, as hints
// for the form (the server enforces them).
Accept []string `json:"accept,omitempty"`
MaxBytes int64 `json:"max_bytes,omitempty"`
}
FieldMeta is the introspection shape of a field (no Column).
type FieldType ¶
type FieldType string
FieldType is a closed admin field type string.
const ( TypeString FieldType = FieldType(field.String) TypeText FieldType = FieldType(field.Text) TypeInteger FieldType = FieldType(field.Integer) TypeFloat FieldType = FieldType(field.Float) TypeDecimal FieldType = FieldType(field.Decimal) TypeBoolean FieldType = FieldType(field.Boolean) TypeDateTime FieldType = FieldType(field.DateTime) TypeDate FieldType = FieldType(field.Date) TypeTime FieldType = FieldType(field.TimeOfDay) TypeDuration FieldType = FieldType(field.Duration) TypeUUID FieldType = FieldType(field.UUID) TypeJSON FieldType = FieldType(field.JSON) TypeRelation FieldType = FieldType(field.Relation) // TypeFile and TypeImage are storage-backed: the column holds an object // key; rows carry a file object; writes take the key of an upload // granted by the admin's upload endpoint. TypeFile FieldType = FieldType(field.File) TypeImage FieldType = FieldType(field.Image) )
Admin meta type strings. These are the admin projection of field.Kind (see docs/fields.md). Do not add a wire string that package field does not already list.
type Host ¶
Host is satisfied by *framework.App. It is defined here so this package does not import framework (framework.New calls Mount).
type ModelMeta ¶
type ModelMeta struct {
Slug string `json:"slug"`
Singular string `json:"singular"`
Plural string `json:"plural"`
PK string `json:"pk"`
Fields []FieldMeta `json:"fields"`
List []string `json:"list"`
Search []string `json:"search"`
Filter []string `json:"filter"`
Ordering []string `json:"ordering"`
Actions Actions `json:"actions"`
Permissions Permissions `json:"permissions"`
Can Capabilities `json:"can"`
}
ModelMeta is one registered model in the introspection API.
type Options ¶
type Options struct {
// Slug is the URL key (products). Required, lowercase, unique per app.
Slug string
// Singular and Plural are UI labels. Empty values are derived at Register
// from the Go type name and slug.
Singular string
Plural string
// PK is the JSON/field name of the primary key. Empty means derive the
// GORM primary key at Register and store it.
PK string
// Fields is the concrete field list handlers read. Empty means derive a
// default from the struct once, inside Register (see FieldsFrom).
Fields []Field
// List is the list-view column order.
List []string
// Search is the list of field names the search query param applies to.
Search []string
// Filter is the list of field names that may appear as list query keys.
Filter []string
// Ordering is the list of field names the ordering query param may use.
// created_at and updated_at may appear here even if omitted from Fields.
Ordering []string
// Actions enables list / detail / create / update / delete. The zero
// value (all false) defaults to all enabled.
Actions Actions
// Permissions are authorization keys enforced by the admin handlers.
// Empty values default to admin.{slug}.{action}.
Permissions Permissions
}
Options is the source of truth for one registered admin model.
type Permissions ¶
type Permissions struct {
View string `json:"view"`
Create string `json:"create"`
Update string `json:"update"`
Delete string `json:"delete"`
}
Permissions holds the keys enforced for each admin operation.
type Relation ¶
type Relation struct {
Slug string `json:"slug"`
Kind string `json:"kind"`
LabelField string `json:"label_field"`
}
Relation describes a belongs_to, has_many, or many_to_many field (#223).
- belongs_to is stored as the foreign key on create/update.
- has_many is read-only. When the field maps to a real GORM has_many association (the usual case, and what auto-derivation emits), list/detail preload it and the data plane returns the related children's primary keys; a has_many field declared without a matching association is meta-only and reads empty. Writes to a has_many field are always rejected.
- many_to_many reads the related primary keys and, on write, syncs the join table to the submitted id list.