| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | package models | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-30 16:28:14 +08:00
										 |  |  | import ( | 
					
						
							|  |  |  | 	"encoding/json" | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-30 16:28:14 +08: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-19 01:33:42 +08:00
										 |  |  | 	CollectionTypeView = "view" | 
					
						
							| 
									
										
										
										
											2022-10-30 16:28:14 +08:00
										 |  |  | ) | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | type Collection struct { | 
					
						
							|  |  |  | 	BaseModel | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-22 23:12:44 +08:00
										 |  |  | 	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 16:28:14 +08: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-07 05:19:05 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-30 16:28:14 +08:00
										 |  |  | // TableName returns the Collection model SQL table name.
 | 
					
						
							| 
									
										
										
										
											2022-07-07 05:19:05 +08: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 16:28:14 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | // IsBase checks if the current collection has "base" type.
 | 
					
						
							|  |  |  | func (m *Collection) IsBase() bool { | 
					
						
							|  |  |  | 	return m.Type == CollectionTypeBase | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-19 01:33:42 +08:00
										 |  |  | // IsAuth checks if the current collection has "auth" type.
 | 
					
						
							| 
									
										
										
										
											2022-10-30 16:28:14 +08:00
										 |  |  | func (m *Collection) IsAuth() bool { | 
					
						
							|  |  |  | 	return m.Type == CollectionTypeAuth | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-19 01:33:42 +08:00
										 |  |  | // IsView checks if the current collection has "view" type.
 | 
					
						
							|  |  |  | func (m *Collection) IsView() bool { | 
					
						
							|  |  |  | 	return m.Type == CollectionTypeView | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-30 16:28:14 +08: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-19 01:33:42 +08: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 16:28:14 +08: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-19 01:33:42 +08:00
										 |  |  | 	case CollectionTypeView: | 
					
						
							|  |  |  | 		typedOptions = m.ViewOptions() | 
					
						
							| 
									
										
										
										
											2022-10-30 16:28:14 +08: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-19 01:33:42 +08:00
										 |  |  | // CollectionBaseOptions defines the "base" Collection.Options fields.
 | 
					
						
							| 
									
										
										
										
											2022-10-30 16:28:14 +08:00
										 |  |  | type CollectionBaseOptions struct { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Validate implements [validation.Validatable] interface.
 | 
					
						
							|  |  |  | func (o CollectionBaseOptions) Validate() error { | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-19 01:33:42 +08:00
										 |  |  | // -------------------------------------------------------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-30 16:28:14 +08: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-19 01:33:42 +08: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), | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | } |