Skip to content

Commit

Permalink
added WithConfig factory to all forms
Browse files Browse the repository at this point in the history
  • Loading branch information
ganigeorgiev committed Aug 7, 2022
1 parent b0ca9b2 commit a426484
Show file tree
Hide file tree
Showing 18 changed files with 542 additions and 195 deletions.
22 changes: 13 additions & 9 deletions forms/admin_login.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
"github.com/pocketbase/pocketbase/models"
)

// AdminLogin defines an admin email/pass login form.
// AdminLogin specifies an admin email/pass login form.
type AdminLogin struct {
config AdminLoginConfig

Expand All @@ -20,20 +20,20 @@ type AdminLogin struct {

// AdminLoginConfig is the [AdminLogin] factory initializer config.
//
// NB! Dao is a required struct member.
// NB! App is a required struct member.
type AdminLoginConfig struct {
Dao *daos.Dao
App core.App
TxDao *daos.Dao
}

// NewAdminLogin creates a new [AdminLogin] form with initializer
// config created from the provided [core.App] instance.
//
// This factory method is used primarily for convenience (and backward compatibility).
// If you want to submit the form as part of another transaction, use
// [NewCollectionUpsertWithConfig] with Dao configured to your txDao.
// [NewAdminLoginWithConfig] with explicitly set TxDao.
func NewAdminLogin(app core.App) *AdminLogin {
return NewAdminLoginWithConfig(AdminLoginConfig{
Dao: app.Dao(),
App: app,
})
}

Expand All @@ -42,8 +42,12 @@ func NewAdminLogin(app core.App) *AdminLogin {
func NewAdminLoginWithConfig(config AdminLoginConfig) *AdminLogin {
form := &AdminLogin{config: config}

if form.config.Dao == nil {
panic("Invalid initializer config.")
if form.config.App == nil {
panic("Missing required config.App instance.")
}

if form.config.TxDao == nil {
form.config.TxDao = form.config.App.Dao()
}

return form
Expand All @@ -64,7 +68,7 @@ func (form *AdminLogin) Submit() (*models.Admin, error) {
return nil, err
}

admin, err := form.config.Dao.FindAdminByEmail(form.Email)
admin, err := form.config.TxDao.FindAdminByEmail(form.Email)
if err != nil {
return nil, err
}
Expand Down
49 changes: 39 additions & 10 deletions forms/admin_password_reset_confirm.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,53 @@ package forms
import (
validation "github.com/go-ozzo/ozzo-validation/v4"
"github.com/pocketbase/pocketbase/core"
"github.com/pocketbase/pocketbase/daos"
"github.com/pocketbase/pocketbase/forms/validators"
"github.com/pocketbase/pocketbase/models"
)

// AdminPasswordResetConfirm defines an admin password reset confirmation form.
// AdminPasswordResetConfirm specifies an admin password reset confirmation form.
type AdminPasswordResetConfirm struct {
app core.App
config AdminPasswordResetConfirmConfig

Token string `form:"token" json:"token"`
Password string `form:"password" json:"password"`
PasswordConfirm string `form:"passwordConfirm" json:"passwordConfirm"`
}

// NewAdminPasswordResetConfirm creates new admin password reset confirmation form.
// AdminPasswordResetConfirmConfig is the [AdminPasswordResetConfirm] factory initializer config.
//
// NB! App is required struct member.
type AdminPasswordResetConfirmConfig struct {
App core.App
TxDao *daos.Dao
}

// NewAdminPasswordResetConfirm creates a new [AdminPasswordResetConfirm]
// form with initializer config created from the provided [core.App] instance.
//
// If you want to submit the form as part of another transaction, use
// [NewAdminPasswordResetConfirmWithConfig] with explicitly set TxDao.
func NewAdminPasswordResetConfirm(app core.App) *AdminPasswordResetConfirm {
return &AdminPasswordResetConfirm{
app: app,
return NewAdminPasswordResetConfirmWithConfig(AdminPasswordResetConfirmConfig{
App: app,
})
}

// NewAdminPasswordResetConfirmWithConfig creates a new [AdminPasswordResetConfirm]
// form with the provided config or panics on invalid configuration.
func NewAdminPasswordResetConfirmWithConfig(config AdminPasswordResetConfirmConfig) *AdminPasswordResetConfirm {
form := &AdminPasswordResetConfirm{config: config}

if form.config.App == nil {
panic("Missing required config.App instance.")
}

if form.config.TxDao == nil {
form.config.TxDao = form.config.App.Dao()
}

return form
}

// Validate makes the form validatable by implementing [validation.Validatable] interface.
Expand All @@ -38,9 +67,9 @@ func (form *AdminPasswordResetConfirm) checkToken(value any) error {
return nil // nothing to check
}

admin, err := form.app.Dao().FindAdminByToken(
admin, err := form.config.TxDao.FindAdminByToken(
v,
form.app.Settings().AdminPasswordResetToken.Secret,
form.config.App.Settings().AdminPasswordResetToken.Secret,
)
if err != nil || admin == nil {
return validation.NewError("validation_invalid_token", "Invalid or expired token.")
Expand All @@ -56,9 +85,9 @@ func (form *AdminPasswordResetConfirm) Submit() (*models.Admin, error) {
return nil, err
}

admin, err := form.app.Dao().FindAdminByToken(
admin, err := form.config.TxDao.FindAdminByToken(
form.Token,
form.app.Settings().AdminPasswordResetToken.Secret,
form.config.App.Settings().AdminPasswordResetToken.Secret,
)
if err != nil {
return nil, err
Expand All @@ -68,7 +97,7 @@ func (form *AdminPasswordResetConfirm) Submit() (*models.Admin, error) {
return nil, err
}

if err := form.app.Dao().SaveAdmin(admin); err != nil {
if err := form.config.TxDao.SaveAdmin(admin); err != nil {
return nil, err
}

Expand Down
51 changes: 40 additions & 11 deletions forms/admin_password_reset_request.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,53 @@ import (
validation "github.com/go-ozzo/ozzo-validation/v4"
"github.com/go-ozzo/ozzo-validation/v4/is"
"github.com/pocketbase/pocketbase/core"
"github.com/pocketbase/pocketbase/daos"
"github.com/pocketbase/pocketbase/mails"
"github.com/pocketbase/pocketbase/tools/types"
)

// AdminPasswordResetRequest defines an admin password reset request form.
// AdminPasswordResetRequest specifies an admin password reset request form.
type AdminPasswordResetRequest struct {
app core.App
resendThreshold float64
config AdminPasswordResetRequestConfig

Email string `form:"email" json:"email"`
}

// NewAdminPasswordResetRequest creates new admin password reset request form.
// AdminPasswordResetRequestConfig is the [AdminPasswordResetRequest] factory initializer config.
//
// NB! App is required struct member.
type AdminPasswordResetRequestConfig struct {
App core.App
TxDao *daos.Dao
ResendThreshold float64 // in seconds
}

// NewAdminPasswordResetRequest creates a new [AdminPasswordResetRequest]
// form with initializer config created from the provided [core.App] instance.
//
// If you want to submit the form as part of another transaction, use
// [NewAdminPasswordResetRequestWithConfig] with explicitly set TxDao.
func NewAdminPasswordResetRequest(app core.App) *AdminPasswordResetRequest {
return &AdminPasswordResetRequest{
app: app,
resendThreshold: 120, // 2 min
return NewAdminPasswordResetRequestWithConfig(AdminPasswordResetRequestConfig{
App: app,
ResendThreshold: 120, // 2min
})
}

// NewAdminPasswordResetRequestWithConfig creates a new [AdminPasswordResetRequest]
// form with the provided config or panics on invalid configuration.
func NewAdminPasswordResetRequestWithConfig(config AdminPasswordResetRequestConfig) *AdminPasswordResetRequest {
form := &AdminPasswordResetRequest{config: config}

if form.config.App == nil {
panic("Missing required config.App instance.")
}

if form.config.TxDao == nil {
form.config.TxDao = form.config.App.Dao()
}

return form
}

// Validate makes the form validatable by implementing [validation.Validatable] interface.
Expand All @@ -48,23 +77,23 @@ func (form *AdminPasswordResetRequest) Submit() error {
return err
}

admin, err := form.app.Dao().FindAdminByEmail(form.Email)
admin, err := form.config.TxDao.FindAdminByEmail(form.Email)
if err != nil {
return err
}

now := time.Now().UTC()
lastResetSentAt := admin.LastResetSentAt.Time()
if now.Sub(lastResetSentAt).Seconds() < form.resendThreshold {
if now.Sub(lastResetSentAt).Seconds() < form.config.ResendThreshold {
return errors.New("You have already requested a password reset.")
}

if err := mails.SendAdminPasswordReset(form.app, admin); err != nil {
if err := mails.SendAdminPasswordReset(form.config.App, admin); err != nil {
return err
}

// update last sent timestamp
admin.LastResetSentAt = types.NowDateTime()

return form.app.Dao().SaveAdmin(admin)
return form.config.TxDao.SaveAdmin(admin)
}
20 changes: 12 additions & 8 deletions forms/admin_upsert.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,21 +23,21 @@ type AdminUpsert struct {

// AdminUpsertConfig is the [AdminUpsert] factory initializer config.
//
// NB! Dao is a required struct member.
// NB! App is a required struct member.
type AdminUpsertConfig struct {
Dao *daos.Dao
App core.App
TxDao *daos.Dao
}

// NewAdminUpsert creates a new [AdminUpsert] form with initializer
// config created from the provided [core.App] and [models.Admin] instances
// (for create you could pass a pointer to an empty Admin - `&models.Admin{}`).
//
// This factory method is used primarily for convenience (and backward compatibility).
// If you want to submit the form as part of another transaction, use
// [NewAdminUpsertWithConfig] with Dao configured to your txDao.
// [NewAdminUpsertWithConfig] with explicitly set TxDao.
func NewAdminUpsert(app core.App, admin *models.Admin) *AdminUpsert {
return NewAdminUpsertWithConfig(AdminUpsertConfig{
Dao: app.Dao(),
App: app,
}, admin)
}

Expand All @@ -50,10 +50,14 @@ func NewAdminUpsertWithConfig(config AdminUpsertConfig, admin *models.Admin) *Ad
admin: admin,
}

if form.config.Dao == nil || form.admin == nil {
if form.config.App == nil || form.admin == nil {
panic("Invalid initializer config or nil upsert model.")
}

if form.config.TxDao == nil {
form.config.TxDao = form.config.App.Dao()
}

// load defaults
form.Id = admin.Id
form.Avatar = admin.Avatar
Expand Down Expand Up @@ -100,7 +104,7 @@ func (form *AdminUpsert) Validate() error {
func (form *AdminUpsert) checkUniqueEmail(value any) error {
v, _ := value.(string)

if form.config.Dao.IsAdminEmailUnique(v, form.admin.Id) {
if form.config.TxDao.IsAdminEmailUnique(v, form.admin.Id) {
return nil
}

Expand Down Expand Up @@ -130,6 +134,6 @@ func (form *AdminUpsert) Submit(interceptors ...InterceptorFunc) error {
}

return runInterceptors(func() error {
return form.config.Dao.SaveAdmin(form.admin)
return form.config.TxDao.SaveAdmin(form.admin)
}, interceptors...)
}
24 changes: 14 additions & 10 deletions forms/collection_upsert.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,21 +33,21 @@ type CollectionUpsert struct {

// CollectionUpsertConfig is the [CollectionUpsert] factory initializer config.
//
// NB! Dao is a required struct member.
// NB! App is a required struct member.
type CollectionUpsertConfig struct {
Dao *daos.Dao
App core.App
TxDao *daos.Dao
}

// NewCollectionUpsert creates a new [CollectionUpsert] form with initializer
// config created from the provided [core.App] and [models.Collection] instances
// (for create you could pass a pointer to an empty Collection - `&models.Collection{}`).
//
// This factory method is used primarily for convenience (and backward compatibility).
// If you want to submit the form as part of another transaction, use
// [NewCollectionUpsertWithConfig] with Dao configured to your txDao.
// [NewCollectionUpsertWithConfig] with explicitly set TxDao.
func NewCollectionUpsert(app core.App, collection *models.Collection) *CollectionUpsert {
return NewCollectionUpsertWithConfig(CollectionUpsertConfig{
Dao: app.Dao(),
App: app,
}, collection)
}

Expand All @@ -60,10 +60,14 @@ func NewCollectionUpsertWithConfig(config CollectionUpsertConfig, collection *mo
collection: collection,
}

if form.config.Dao == nil || form.collection == nil {
if form.config.App == nil || form.collection == nil {
panic("Invalid initializer config or nil upsert model.")
}

if form.config.TxDao == nil {
form.config.TxDao = form.config.App.Dao()
}

// load defaults
form.Id = form.collection.Id
form.Name = form.collection.Name
Expand Down Expand Up @@ -123,11 +127,11 @@ func (form *CollectionUpsert) Validate() error {
func (form *CollectionUpsert) checkUniqueName(value any) error {
v, _ := value.(string)

if !form.config.Dao.IsCollectionNameUnique(v, form.collection.Id) {
if !form.config.TxDao.IsCollectionNameUnique(v, form.collection.Id) {
return validation.NewError("validation_collection_name_exists", "Collection name must be unique (case insensitive).")
}

if (form.collection.IsNew() || !strings.EqualFold(v, form.collection.Name)) && form.config.Dao.HasTable(v) {
if (form.collection.IsNew() || !strings.EqualFold(v, form.collection.Name)) && form.config.TxDao.HasTable(v) {
return validation.NewError("validation_collection_name_table_exists", "The collection name must be also unique table name.")
}

Expand Down Expand Up @@ -194,7 +198,7 @@ func (form *CollectionUpsert) checkRule(value any) error {
}

dummy := &models.Collection{Schema: form.Schema}
r := resolvers.NewRecordFieldResolver(form.config.Dao, dummy, nil)
r := resolvers.NewRecordFieldResolver(form.config.TxDao, dummy, nil)

_, err := search.FilterData(*v).BuildExpr(r)
if err != nil {
Expand Down Expand Up @@ -239,6 +243,6 @@ func (form *CollectionUpsert) Submit(interceptors ...InterceptorFunc) error {
form.collection.DeleteRule = form.DeleteRule

return runInterceptors(func() error {
return form.config.Dao.SaveCollection(form.collection)
return form.config.TxDao.SaveCollection(form.collection)
}, interceptors...)
}
Loading

0 comments on commit a426484

Please sign in to comment.