Files
base/core/collection_model_base_options.go
zeekay cebf25db06 A collection can admit visitors from other orgs
A Base its host opened for one org refused every token acting in
another, so a reader signed in with Hanzo ID could not comment on a
site whose Base is org hanzo's.  Opening that org to any account would
hand the CRM to anyone, since its rules admit any signed-in caller.

A base collection now admits visitors when it says so, with
"visitors": true.  A visitor reaches only its records and files; every
other route, and every collection that has not opted in, still answers
403.  Its record carries role "visitor", admin false and its own org,
so `author = @request.auth.id` holds a row to its writer.  Any other
collection's rules read a visitor as a guest, so a relation, expand or
filter from a visitors' collection carries it no further.  Its writes
are held to ten a minute per Base, keyed by subject, whatever the
deployment limits.  A superuser is never a visitor.
2026-10-20 18:10:41 -07:00

51 lines
2.0 KiB
Go

package core
import (
validation "github.com/go-ozzo/ozzo-validation/v4"
)
var _ optionsValidator = (*collectionBaseOptions)(nil)
// collectionBaseOptions defines the options for the "base" type collection.
type collectionBaseOptions struct {
// History keeps one _history row for every create, update and delete of a
// record in this collection, written in the record's own transaction: who
// did it, when, and which fields changed from what to what. Off unless a
// collection asks for it.
History bool `form:"history" json:"history,omitempty"`
// Visitors admits a visitor to the collection: a person IAM vouched for
// whose token acts in another org than the one whose Base this is. Off,
// which is every collection until one asks, a visitor is refused here as
// anywhere else. On, its rules decide, reading the visitor as
// `@request.auth.role = "visitor"`. See [Collection.AdmitsVisitors].
Visitors bool `form:"visitors" json:"visitors,omitempty"`
// Label is what a person calls one record ("Person"), Plural what they
// call many ("People"). Empty means the collection's name.
Label string `form:"label" json:"label,omitempty"`
Plural string `form:"plural" json:"plural,omitempty"`
// Icon names the icon drawn for the collection, in the same vocabulary
// as a field's.
Icon string `form:"icon" json:"icon,omitempty"`
// Description says what the collection holds.
Description string `form:"description" json:"description,omitempty"`
}
// AdmitsVisitors reports whether a visitor may reach the collection's records
// and files. Only a base collection can, and only when it says so.
func (c *Collection) AdmitsVisitors() bool {
return c != nil && c.IsBase() && c.Visitors
}
func (o *collectionBaseOptions) validate(cv *collectionValidator) error {
return validation.ValidateStruct(o,
validation.Field(&o.Label, validation.Length(0, 255)),
validation.Field(&o.Plural, validation.Length(0, 255)),
validation.Field(&o.Icon, validation.Match(iconRegex)),
validation.Field(&o.Description, validation.Length(0, 1000)),
)
}