1
0
mirror of https://github.com/pocketbase/pocketbase.git synced 2024-11-28 18:11:17 +02:00
pocketbase/models/collection.go

220 lines
6.1 KiB
Go
Raw Normal View History

2022-07-06 23:19:05 +02:00
package models
2022-10-30 10:28:14 +02:00
import (
"encoding/json"
2022-07-06 23:19:05 +02:00
2022-10-30 10:28:14 +02:00
validation "github.com/go-ozzo/ozzo-validation/v4"
"github.com/go-ozzo/ozzo-validation/v4/is"
"github.com/pocketbase/pocketbase/models/schema"
"github.com/pocketbase/pocketbase/tools/types"
)
var (
_ Model = (*Collection)(nil)
_ FilesManager = (*Collection)(nil)
)
const (
CollectionTypeBase = "base"
CollectionTypeAuth = "auth"
2023-02-18 19:33:42 +02:00
CollectionTypeView = "view"
2022-10-30 10:28:14 +02:00
)
2022-07-06 23:19:05 +02:00
type Collection struct {
BaseModel
Name string `db:"name" json:"name"`
Type string `db:"type" json:"type"`
System bool `db:"system" json:"system"`
Schema schema.Schema `db:"schema" json:"schema"`
Indexes types.JsonArray[string] `db:"indexes" json:"indexes"`
2022-10-30 10:28:14 +02:00
// rules
ListRule *string `db:"listRule" json:"listRule"`
ViewRule *string `db:"viewRule" json:"viewRule"`
CreateRule *string `db:"createRule" json:"createRule"`
UpdateRule *string `db:"updateRule" json:"updateRule"`
DeleteRule *string `db:"deleteRule" json:"deleteRule"`
Options types.JsonMap `db:"options" json:"options"`
2022-07-06 23:19:05 +02:00
}
2022-10-30 10:28:14 +02:00
// TableName returns the Collection model SQL table name.
2022-07-06 23:19:05 +02:00
func (m *Collection) TableName() string {
return "_collections"
}
// BaseFilesPath returns the storage dir path used by the collection.
func (m *Collection) BaseFilesPath() string {
return m.Id
}
2022-10-30 10:28:14 +02:00
// IsBase checks if the current collection has "base" type.
func (m *Collection) IsBase() bool {
return m.Type == CollectionTypeBase
}
2023-02-18 19:33:42 +02:00
// IsAuth checks if the current collection has "auth" type.
2022-10-30 10:28:14 +02:00
func (m *Collection) IsAuth() bool {
return m.Type == CollectionTypeAuth
}
2023-02-18 19:33:42 +02:00
// IsView checks if the current collection has "view" type.
func (m *Collection) IsView() bool {
return m.Type == CollectionTypeView
}
2022-10-30 10:28:14 +02:00
// MarshalJSON implements the [json.Marshaler] interface.
func (m Collection) MarshalJSON() ([]byte, error) {
type alias Collection // prevent recursion
m.NormalizeOptions()
return json.Marshal(alias(m))
}
// BaseOptions decodes the current collection options and returns them
// as new [CollectionBaseOptions] instance.
func (m *Collection) BaseOptions() CollectionBaseOptions {
result := CollectionBaseOptions{}
m.DecodeOptions(&result)
return result
}
// AuthOptions decodes the current collection options and returns them
// as new [CollectionAuthOptions] instance.
func (m *Collection) AuthOptions() CollectionAuthOptions {
result := CollectionAuthOptions{}
m.DecodeOptions(&result)
return result
}
2023-02-18 19:33:42 +02:00
// ViewOptions decodes the current collection options and returns them
// as new [CollectionViewOptions] instance.
func (m *Collection) ViewOptions() CollectionViewOptions {
result := CollectionViewOptions{}
m.DecodeOptions(&result)
return result
}
2022-10-30 10:28:14 +02:00
// NormalizeOptions updates the current collection options with a
// new normalized state based on the collection type.
func (m *Collection) NormalizeOptions() error {
var typedOptions any
switch m.Type {
case CollectionTypeAuth:
typedOptions = m.AuthOptions()
2023-02-18 19:33:42 +02:00
case CollectionTypeView:
typedOptions = m.ViewOptions()
2022-10-30 10:28:14 +02:00
default:
typedOptions = m.BaseOptions()
}
// serialize
raw, err := json.Marshal(typedOptions)
if err != nil {
return err
}
// load into a new JsonMap
m.Options = types.JsonMap{}
if err := json.Unmarshal(raw, &m.Options); err != nil {
return err
}
return nil
}
// DecodeOptions decodes the current collection options into the
// provided "result" (must be a pointer).
func (m *Collection) DecodeOptions(result any) error {
// raw serialize
raw, err := json.Marshal(m.Options)
if err != nil {
return err
}
// decode into the provided result
if err := json.Unmarshal(raw, result); err != nil {
return err
}
return nil
}
// SetOptions normalizes and unmarshals the specified options into m.Options.
func (m *Collection) SetOptions(typedOptions any) error {
// serialize
raw, err := json.Marshal(typedOptions)
if err != nil {
return err
}
m.Options = types.JsonMap{}
if err := json.Unmarshal(raw, &m.Options); err != nil {
return err
}
return m.NormalizeOptions()
}
// -------------------------------------------------------------------
2023-02-18 19:33:42 +02:00
// CollectionBaseOptions defines the "base" Collection.Options fields.
2022-10-30 10:28:14 +02:00
type CollectionBaseOptions struct {
}
// Validate implements [validation.Validatable] interface.
func (o CollectionBaseOptions) Validate() error {
return nil
}
2023-02-18 19:33:42 +02:00
// -------------------------------------------------------------------
2022-10-30 10:28:14 +02:00
// CollectionAuthOptions defines the "auth" Collection.Options fields.
type CollectionAuthOptions struct {
ManageRule *string `form:"manageRule" json:"manageRule"`
AllowOAuth2Auth bool `form:"allowOAuth2Auth" json:"allowOAuth2Auth"`
AllowUsernameAuth bool `form:"allowUsernameAuth" json:"allowUsernameAuth"`
AllowEmailAuth bool `form:"allowEmailAuth" json:"allowEmailAuth"`
RequireEmail bool `form:"requireEmail" json:"requireEmail"`
ExceptEmailDomains []string `form:"exceptEmailDomains" json:"exceptEmailDomains"`
OnlyEmailDomains []string `form:"onlyEmailDomains" json:"onlyEmailDomains"`
MinPasswordLength int `form:"minPasswordLength" json:"minPasswordLength"`
}
// Validate implements [validation.Validatable] interface.
func (o CollectionAuthOptions) Validate() error {
return validation.ValidateStruct(&o,
validation.Field(&o.ManageRule, validation.NilOrNotEmpty),
validation.Field(
&o.ExceptEmailDomains,
validation.When(len(o.OnlyEmailDomains) > 0, validation.Empty).Else(validation.Each(is.Domain)),
),
validation.Field(
&o.OnlyEmailDomains,
validation.When(len(o.ExceptEmailDomains) > 0, validation.Empty).Else(validation.Each(is.Domain)),
),
validation.Field(
&o.MinPasswordLength,
validation.When(o.AllowUsernameAuth || o.AllowEmailAuth, validation.Required),
validation.Min(5),
validation.Max(72),
),
)
}
2023-02-18 19:33:42 +02:00
// -------------------------------------------------------------------
// CollectionViewOptions defines the "view" Collection.Options fields.
type CollectionViewOptions struct {
Query string `form:"query" json:"query"`
}
// Validate implements [validation.Validatable] interface.
func (o CollectionViewOptions) Validate() error {
return validation.ValidateStruct(&o,
validation.Field(&o.Query, validation.Required),
)
}