[#80] fixed before hooks data and added optional interceptor to upsert submit
This commit is contained in:
parent
ce857985be
commit
05a4071eba
|
@ -166,7 +166,7 @@ func (api *adminApi) create(c echo.Context) error {
|
||||||
|
|
||||||
// load request
|
// load request
|
||||||
if err := c.Bind(form); err != nil {
|
if err := c.Bind(form); err != nil {
|
||||||
return rest.NewBadRequestError("Failed to read the submitted data due to invalid formatting.", err)
|
return rest.NewBadRequestError("Failed to load the submitted data due to invalid formatting.", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
event := &core.AdminCreateEvent{
|
event := &core.AdminCreateEvent{
|
||||||
|
@ -174,20 +174,24 @@ func (api *adminApi) create(c echo.Context) error {
|
||||||
Admin: admin,
|
Admin: admin,
|
||||||
}
|
}
|
||||||
|
|
||||||
handlerErr := api.app.OnAdminBeforeCreateRequest().Trigger(event, func(e *core.AdminCreateEvent) error {
|
|
||||||
// create the admin
|
// create the admin
|
||||||
if err := form.Submit(); err != nil {
|
submitErr := form.Submit(func(next forms.InterceptorNextFunc) forms.InterceptorNextFunc {
|
||||||
|
return func() error {
|
||||||
|
return api.app.OnAdminBeforeCreateRequest().Trigger(event, func(e *core.AdminCreateEvent) error {
|
||||||
|
if err := next(); err != nil {
|
||||||
return rest.NewBadRequestError("Failed to create admin.", err)
|
return rest.NewBadRequestError("Failed to create admin.", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return e.HttpContext.JSON(http.StatusOK, e.Admin)
|
return e.HttpContext.JSON(http.StatusOK, e.Admin)
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
if handlerErr == nil {
|
if submitErr == nil {
|
||||||
api.app.OnAdminAfterCreateRequest().Trigger(event)
|
api.app.OnAdminAfterCreateRequest().Trigger(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
return handlerErr
|
return submitErr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *adminApi) update(c echo.Context) error {
|
func (api *adminApi) update(c echo.Context) error {
|
||||||
|
@ -205,7 +209,7 @@ func (api *adminApi) update(c echo.Context) error {
|
||||||
|
|
||||||
// load request
|
// load request
|
||||||
if err := c.Bind(form); err != nil {
|
if err := c.Bind(form); err != nil {
|
||||||
return rest.NewBadRequestError("Failed to read the submitted data due to invalid formatting.", err)
|
return rest.NewBadRequestError("Failed to load the submitted data due to invalid formatting.", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
event := &core.AdminUpdateEvent{
|
event := &core.AdminUpdateEvent{
|
||||||
|
@ -213,20 +217,24 @@ func (api *adminApi) update(c echo.Context) error {
|
||||||
Admin: admin,
|
Admin: admin,
|
||||||
}
|
}
|
||||||
|
|
||||||
handlerErr := api.app.OnAdminBeforeUpdateRequest().Trigger(event, func(e *core.AdminUpdateEvent) error {
|
|
||||||
// update the admin
|
// update the admin
|
||||||
if err := form.Submit(); err != nil {
|
submitErr := form.Submit(func(next forms.InterceptorNextFunc) forms.InterceptorNextFunc {
|
||||||
|
return func() error {
|
||||||
|
return api.app.OnAdminBeforeUpdateRequest().Trigger(event, func(e *core.AdminUpdateEvent) error {
|
||||||
|
if err := next(); err != nil {
|
||||||
return rest.NewBadRequestError("Failed to update admin.", err)
|
return rest.NewBadRequestError("Failed to update admin.", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return e.HttpContext.JSON(http.StatusOK, e.Admin)
|
return e.HttpContext.JSON(http.StatusOK, e.Admin)
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
if handlerErr == nil {
|
if submitErr == nil {
|
||||||
api.app.OnAdminAfterUpdateRequest().Trigger(event)
|
api.app.OnAdminAfterUpdateRequest().Trigger(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
return handlerErr
|
return submitErr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *adminApi) delete(c echo.Context) error {
|
func (api *adminApi) delete(c echo.Context) error {
|
||||||
|
|
|
@ -507,9 +507,6 @@ func TestAdminCreate(t *testing.T) {
|
||||||
},
|
},
|
||||||
ExpectedStatus: 400,
|
ExpectedStatus: 400,
|
||||||
ExpectedContent: []string{`"data":{"email":{"code":"validation_required","message":"Cannot be blank."},"password":{"code":"validation_required","message":"Cannot be blank."}}`},
|
ExpectedContent: []string{`"data":{"email":{"code":"validation_required","message":"Cannot be blank."},"password":{"code":"validation_required","message":"Cannot be blank."}}`},
|
||||||
ExpectedEvents: map[string]int{
|
|
||||||
"OnAdminBeforeCreateRequest": 1,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "authorized as admin + invalid data format",
|
Name: "authorized as admin + invalid data format",
|
||||||
|
@ -532,9 +529,6 @@ func TestAdminCreate(t *testing.T) {
|
||||||
},
|
},
|
||||||
ExpectedStatus: 400,
|
ExpectedStatus: 400,
|
||||||
ExpectedContent: []string{`"data":{"avatar":{"code":"validation_max_less_equal_than_required","message":"Must be no greater than 9."},"email":{"code":"validation_admin_email_exists","message":"Admin email already exists."},"password":{"code":"validation_length_out_of_range","message":"The length must be between 10 and 100."},"passwordConfirm":{"code":"validation_values_mismatch","message":"Values don't match."}}`},
|
ExpectedContent: []string{`"data":{"avatar":{"code":"validation_max_less_equal_than_required","message":"Must be no greater than 9."},"email":{"code":"validation_admin_email_exists","message":"Admin email already exists."},"password":{"code":"validation_length_out_of_range","message":"The length must be between 10 and 100."},"passwordConfirm":{"code":"validation_values_mismatch","message":"Values don't match."}}`},
|
||||||
ExpectedEvents: map[string]int{
|
|
||||||
"OnAdminBeforeCreateRequest": 1,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "authorized as admin + valid data",
|
Name: "authorized as admin + valid data",
|
||||||
|
@ -647,9 +641,6 @@ func TestAdminUpdate(t *testing.T) {
|
||||||
},
|
},
|
||||||
ExpectedStatus: 400,
|
ExpectedStatus: 400,
|
||||||
ExpectedContent: []string{`"data":{"avatar":{"code":"validation_max_less_equal_than_required","message":"Must be no greater than 9."},"email":{"code":"validation_admin_email_exists","message":"Admin email already exists."},"password":{"code":"validation_length_out_of_range","message":"The length must be between 10 and 100."},"passwordConfirm":{"code":"validation_values_mismatch","message":"Values don't match."}}`},
|
ExpectedContent: []string{`"data":{"avatar":{"code":"validation_max_less_equal_than_required","message":"Must be no greater than 9."},"email":{"code":"validation_admin_email_exists","message":"Admin email already exists."},"password":{"code":"validation_length_out_of_range","message":"The length must be between 10 and 100."},"passwordConfirm":{"code":"validation_values_mismatch","message":"Values don't match."}}`},
|
||||||
ExpectedEvents: map[string]int{
|
|
||||||
"OnAdminBeforeUpdateRequest": 1,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Method: http.MethodPatch,
|
Method: http.MethodPatch,
|
||||||
|
|
|
@ -76,9 +76,9 @@ func (api *collectionApi) create(c echo.Context) error {
|
||||||
|
|
||||||
form := forms.NewCollectionUpsert(api.app, collection)
|
form := forms.NewCollectionUpsert(api.app, collection)
|
||||||
|
|
||||||
// read
|
// load request
|
||||||
if err := c.Bind(form); err != nil {
|
if err := c.Bind(form); err != nil {
|
||||||
return rest.NewBadRequestError("Failed to read the submitted data due to invalid formatting.", err)
|
return rest.NewBadRequestError("Failed to load the submitted data due to invalid formatting.", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
event := &core.CollectionCreateEvent{
|
event := &core.CollectionCreateEvent{
|
||||||
|
@ -86,20 +86,24 @@ func (api *collectionApi) create(c echo.Context) error {
|
||||||
Collection: collection,
|
Collection: collection,
|
||||||
}
|
}
|
||||||
|
|
||||||
handlerErr := api.app.OnCollectionBeforeCreateRequest().Trigger(event, func(e *core.CollectionCreateEvent) error {
|
// create the collection
|
||||||
// submit
|
submitErr := form.Submit(func(next forms.InterceptorNextFunc) forms.InterceptorNextFunc {
|
||||||
if err := form.Submit(); err != nil {
|
return func() error {
|
||||||
|
return api.app.OnCollectionBeforeCreateRequest().Trigger(event, func(e *core.CollectionCreateEvent) error {
|
||||||
|
if err := next(); err != nil {
|
||||||
return rest.NewBadRequestError("Failed to create the collection.", err)
|
return rest.NewBadRequestError("Failed to create the collection.", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return e.HttpContext.JSON(http.StatusOK, e.Collection)
|
return e.HttpContext.JSON(http.StatusOK, e.Collection)
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
if handlerErr == nil {
|
if submitErr == nil {
|
||||||
api.app.OnCollectionAfterCreateRequest().Trigger(event)
|
api.app.OnCollectionAfterCreateRequest().Trigger(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
return handlerErr
|
return submitErr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *collectionApi) update(c echo.Context) error {
|
func (api *collectionApi) update(c echo.Context) error {
|
||||||
|
@ -110,9 +114,9 @@ func (api *collectionApi) update(c echo.Context) error {
|
||||||
|
|
||||||
form := forms.NewCollectionUpsert(api.app, collection)
|
form := forms.NewCollectionUpsert(api.app, collection)
|
||||||
|
|
||||||
// read
|
// load request
|
||||||
if err := c.Bind(form); err != nil {
|
if err := c.Bind(form); err != nil {
|
||||||
return rest.NewBadRequestError("Failed to read the submitted data due to invalid formatting.", err)
|
return rest.NewBadRequestError("Failed to load the submitted data due to invalid formatting.", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
event := &core.CollectionUpdateEvent{
|
event := &core.CollectionUpdateEvent{
|
||||||
|
@ -120,20 +124,24 @@ func (api *collectionApi) update(c echo.Context) error {
|
||||||
Collection: collection,
|
Collection: collection,
|
||||||
}
|
}
|
||||||
|
|
||||||
handlerErr := api.app.OnCollectionBeforeUpdateRequest().Trigger(event, func(e *core.CollectionUpdateEvent) error {
|
// update the collection
|
||||||
// submit
|
submitErr := form.Submit(func(next forms.InterceptorNextFunc) forms.InterceptorNextFunc {
|
||||||
if err := form.Submit(); err != nil {
|
return func() error {
|
||||||
|
return api.app.OnCollectionBeforeUpdateRequest().Trigger(event, func(e *core.CollectionUpdateEvent) error {
|
||||||
|
if err := next(); err != nil {
|
||||||
return rest.NewBadRequestError("Failed to update the collection.", err)
|
return rest.NewBadRequestError("Failed to update the collection.", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return e.HttpContext.JSON(http.StatusOK, e.Collection)
|
return e.HttpContext.JSON(http.StatusOK, e.Collection)
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
if handlerErr == nil {
|
if submitErr == nil {
|
||||||
api.app.OnCollectionAfterUpdateRequest().Trigger(event)
|
api.app.OnCollectionAfterUpdateRequest().Trigger(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
return handlerErr
|
return submitErr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *collectionApi) delete(c echo.Context) error {
|
func (api *collectionApi) delete(c echo.Context) error {
|
||||||
|
|
|
@ -297,9 +297,6 @@ func TestCollectionCreate(t *testing.T) {
|
||||||
`"name":{"code":"validation_required"`,
|
`"name":{"code":"validation_required"`,
|
||||||
`"schema":{"code":"validation_required"`,
|
`"schema":{"code":"validation_required"`,
|
||||||
},
|
},
|
||||||
ExpectedEvents: map[string]int{
|
|
||||||
"OnCollectionBeforeCreateRequest": 1,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "authorized as admin + invalid data (eg. existing name)",
|
Name: "authorized as admin + invalid data (eg. existing name)",
|
||||||
|
@ -315,9 +312,6 @@ func TestCollectionCreate(t *testing.T) {
|
||||||
`"name":{"code":"validation_collection_name_exists"`,
|
`"name":{"code":"validation_collection_name_exists"`,
|
||||||
`"schema":{"0":{"name":{"code":"validation_required"`,
|
`"schema":{"0":{"name":{"code":"validation_required"`,
|
||||||
},
|
},
|
||||||
ExpectedEvents: map[string]int{
|
|
||||||
"OnCollectionBeforeCreateRequest": 1,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "authorized as admin + valid data",
|
Name: "authorized as admin + valid data",
|
||||||
|
@ -399,9 +393,6 @@ func TestCollectionUpdate(t *testing.T) {
|
||||||
`"data":{`,
|
`"data":{`,
|
||||||
`"name":{"code":"validation_collection_name_exists"`,
|
`"name":{"code":"validation_collection_name_exists"`,
|
||||||
},
|
},
|
||||||
ExpectedEvents: map[string]int{
|
|
||||||
"OnCollectionBeforeUpdateRequest": 1,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "authorized as admin + valid data",
|
Name: "authorized as admin + valid data",
|
||||||
|
|
|
@ -193,7 +193,7 @@ func (api *recordApi) create(c echo.Context) error {
|
||||||
testRecord := models.NewRecord(collection)
|
testRecord := models.NewRecord(collection)
|
||||||
testForm := forms.NewRecordUpsert(api.app, testRecord)
|
testForm := forms.NewRecordUpsert(api.app, testRecord)
|
||||||
if err := testForm.LoadData(c.Request()); err != nil {
|
if err := testForm.LoadData(c.Request()); err != nil {
|
||||||
return rest.NewBadRequestError("Failed to read the submitted data due to invalid formatting.", err)
|
return rest.NewBadRequestError("Failed to load the submitted data due to invalid formatting.", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
testErr := testForm.DrySubmit(func(txDao *daos.Dao) error {
|
testErr := testForm.DrySubmit(func(txDao *daos.Dao) error {
|
||||||
|
@ -210,7 +210,7 @@ func (api *recordApi) create(c echo.Context) error {
|
||||||
|
|
||||||
// load request
|
// load request
|
||||||
if err := form.LoadData(c.Request()); err != nil {
|
if err := form.LoadData(c.Request()); err != nil {
|
||||||
return rest.NewBadRequestError("Failed to read the submitted data due to invalid formatting.", err)
|
return rest.NewBadRequestError("Failed to load the submitted data due to invalid formatting.", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
event := &core.RecordCreateEvent{
|
event := &core.RecordCreateEvent{
|
||||||
|
@ -218,20 +218,24 @@ func (api *recordApi) create(c echo.Context) error {
|
||||||
Record: record,
|
Record: record,
|
||||||
}
|
}
|
||||||
|
|
||||||
handlerErr := api.app.OnRecordBeforeCreateRequest().Trigger(event, func(e *core.RecordCreateEvent) error {
|
|
||||||
// create the record
|
// create the record
|
||||||
if err := form.Submit(); err != nil {
|
submitErr := form.Submit(func(next forms.InterceptorNextFunc) forms.InterceptorNextFunc {
|
||||||
|
return func() error {
|
||||||
|
return api.app.OnRecordBeforeCreateRequest().Trigger(event, func(e *core.RecordCreateEvent) error {
|
||||||
|
if err := next(); err != nil {
|
||||||
return rest.NewBadRequestError("Failed to create record.", err)
|
return rest.NewBadRequestError("Failed to create record.", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return e.HttpContext.JSON(http.StatusOK, e.Record)
|
return e.HttpContext.JSON(http.StatusOK, e.Record)
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
if handlerErr == nil {
|
if submitErr == nil {
|
||||||
api.app.OnRecordAfterCreateRequest().Trigger(event)
|
api.app.OnRecordAfterCreateRequest().Trigger(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
return handlerErr
|
return submitErr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *recordApi) update(c echo.Context) error {
|
func (api *recordApi) update(c echo.Context) error {
|
||||||
|
@ -276,7 +280,7 @@ func (api *recordApi) update(c echo.Context) error {
|
||||||
|
|
||||||
// load request
|
// load request
|
||||||
if err := form.LoadData(c.Request()); err != nil {
|
if err := form.LoadData(c.Request()); err != nil {
|
||||||
return rest.NewBadRequestError("Failed to read the submitted data due to invalid formatting.", err)
|
return rest.NewBadRequestError("Failed to load the submitted data due to invalid formatting.", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
event := &core.RecordUpdateEvent{
|
event := &core.RecordUpdateEvent{
|
||||||
|
@ -284,20 +288,24 @@ func (api *recordApi) update(c echo.Context) error {
|
||||||
Record: record,
|
Record: record,
|
||||||
}
|
}
|
||||||
|
|
||||||
handlerErr := api.app.OnRecordBeforeUpdateRequest().Trigger(event, func(e *core.RecordUpdateEvent) error {
|
|
||||||
// update the record
|
// update the record
|
||||||
if err := form.Submit(); err != nil {
|
submitErr := form.Submit(func(next forms.InterceptorNextFunc) forms.InterceptorNextFunc {
|
||||||
|
return func() error {
|
||||||
|
return api.app.OnRecordBeforeUpdateRequest().Trigger(event, func(e *core.RecordUpdateEvent) error {
|
||||||
|
if err := next(); err != nil {
|
||||||
return rest.NewBadRequestError("Failed to update record.", err)
|
return rest.NewBadRequestError("Failed to update record.", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return e.HttpContext.JSON(http.StatusOK, e.Record)
|
return e.HttpContext.JSON(http.StatusOK, e.Record)
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
if handlerErr == nil {
|
if submitErr == nil {
|
||||||
api.app.OnRecordAfterUpdateRequest().Trigger(event)
|
api.app.OnRecordAfterUpdateRequest().Trigger(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
return handlerErr
|
return submitErr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *recordApi) delete(c echo.Context) error {
|
func (api *recordApi) delete(c echo.Context) error {
|
||||||
|
|
|
@ -40,6 +40,8 @@ func (api *settingsApi) list(c echo.Context) error {
|
||||||
|
|
||||||
func (api *settingsApi) set(c echo.Context) error {
|
func (api *settingsApi) set(c echo.Context) error {
|
||||||
form := forms.NewSettingsUpsert(api.app)
|
form := forms.NewSettingsUpsert(api.app)
|
||||||
|
|
||||||
|
// load request
|
||||||
if err := c.Bind(form); err != nil {
|
if err := c.Bind(form); err != nil {
|
||||||
return rest.NewBadRequestError("An error occurred while reading the submitted data.", err)
|
return rest.NewBadRequestError("An error occurred while reading the submitted data.", err)
|
||||||
}
|
}
|
||||||
|
@ -50,8 +52,11 @@ func (api *settingsApi) set(c echo.Context) error {
|
||||||
NewSettings: form.Settings,
|
NewSettings: form.Settings,
|
||||||
}
|
}
|
||||||
|
|
||||||
handlerErr := api.app.OnSettingsBeforeUpdateRequest().Trigger(event, func(e *core.SettingsUpdateEvent) error {
|
// update the settings
|
||||||
if err := form.Submit(); err != nil {
|
submitErr := form.Submit(func(next forms.InterceptorNextFunc) forms.InterceptorNextFunc {
|
||||||
|
return func() error {
|
||||||
|
return api.app.OnSettingsBeforeUpdateRequest().Trigger(event, func(e *core.SettingsUpdateEvent) error {
|
||||||
|
if err := next(); err != nil {
|
||||||
return rest.NewBadRequestError("An error occurred while submitting the form.", err)
|
return rest.NewBadRequestError("An error occurred while submitting the form.", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,10 +67,12 @@ func (api *settingsApi) set(c echo.Context) error {
|
||||||
|
|
||||||
return e.HttpContext.JSON(http.StatusOK, redactedSettings)
|
return e.HttpContext.JSON(http.StatusOK, redactedSettings)
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
if handlerErr == nil {
|
if submitErr == nil {
|
||||||
api.app.OnSettingsAfterUpdateRequest().Trigger(event)
|
api.app.OnSettingsAfterUpdateRequest().Trigger(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
return handlerErr
|
return submitErr
|
||||||
}
|
}
|
||||||
|
|
|
@ -139,9 +139,6 @@ func TestSettingsSet(t *testing.T) {
|
||||||
`"emailAuth":{"minPasswordLength":{"code":"validation_min_greater_equal_than_required","message":"Must be no less than 5."}}`,
|
`"emailAuth":{"minPasswordLength":{"code":"validation_min_greater_equal_than_required","message":"Must be no less than 5."}}`,
|
||||||
`"meta":{"appName":{"code":"validation_required","message":"Cannot be blank."}}`,
|
`"meta":{"appName":{"code":"validation_required","message":"Cannot be blank."}}`,
|
||||||
},
|
},
|
||||||
ExpectedEvents: map[string]int{
|
|
||||||
"OnSettingsBeforeUpdateRequest": 1,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "authorized as admin submitting valid data",
|
Name: "authorized as admin submitting valid data",
|
||||||
|
|
28
apis/user.go
28
apis/user.go
|
@ -348,7 +348,7 @@ func (api *userApi) create(c echo.Context) error {
|
||||||
|
|
||||||
// load request
|
// load request
|
||||||
if err := c.Bind(form); err != nil {
|
if err := c.Bind(form); err != nil {
|
||||||
return rest.NewBadRequestError("Failed to read the submitted data due to invalid formatting.", err)
|
return rest.NewBadRequestError("Failed to load the submitted data due to invalid formatting.", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
event := &core.UserCreateEvent{
|
event := &core.UserCreateEvent{
|
||||||
|
@ -356,20 +356,24 @@ func (api *userApi) create(c echo.Context) error {
|
||||||
User: user,
|
User: user,
|
||||||
}
|
}
|
||||||
|
|
||||||
handlerErr := api.app.OnUserBeforeCreateRequest().Trigger(event, func(e *core.UserCreateEvent) error {
|
|
||||||
// create the user
|
// create the user
|
||||||
if err := form.Submit(); err != nil {
|
submitErr := form.Submit(func(next forms.InterceptorNextFunc) forms.InterceptorNextFunc {
|
||||||
|
return func() error {
|
||||||
|
return api.app.OnUserBeforeCreateRequest().Trigger(event, func(e *core.UserCreateEvent) error {
|
||||||
|
if err := next(); err != nil {
|
||||||
return rest.NewBadRequestError("Failed to create user.", err)
|
return rest.NewBadRequestError("Failed to create user.", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return e.HttpContext.JSON(http.StatusOK, e.User)
|
return e.HttpContext.JSON(http.StatusOK, e.User)
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
if handlerErr == nil {
|
if submitErr == nil {
|
||||||
api.app.OnUserAfterCreateRequest().Trigger(event)
|
api.app.OnUserAfterCreateRequest().Trigger(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
return handlerErr
|
return submitErr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *userApi) update(c echo.Context) error {
|
func (api *userApi) update(c echo.Context) error {
|
||||||
|
@ -387,7 +391,7 @@ func (api *userApi) update(c echo.Context) error {
|
||||||
|
|
||||||
// load request
|
// load request
|
||||||
if err := c.Bind(form); err != nil {
|
if err := c.Bind(form); err != nil {
|
||||||
return rest.NewBadRequestError("Failed to read the submitted data due to invalid formatting.", err)
|
return rest.NewBadRequestError("Failed to load the submitted data due to invalid formatting.", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
event := &core.UserUpdateEvent{
|
event := &core.UserUpdateEvent{
|
||||||
|
@ -395,20 +399,24 @@ func (api *userApi) update(c echo.Context) error {
|
||||||
User: user,
|
User: user,
|
||||||
}
|
}
|
||||||
|
|
||||||
handlerErr := api.app.OnUserBeforeUpdateRequest().Trigger(event, func(e *core.UserUpdateEvent) error {
|
|
||||||
// update the user
|
// update the user
|
||||||
if err := form.Submit(); err != nil {
|
submitErr := form.Submit(func(next forms.InterceptorNextFunc) forms.InterceptorNextFunc {
|
||||||
|
return func() error {
|
||||||
|
return api.app.OnUserBeforeUpdateRequest().Trigger(event, func(e *core.UserUpdateEvent) error {
|
||||||
|
if err := next(); err != nil {
|
||||||
return rest.NewBadRequestError("Failed to update user.", err)
|
return rest.NewBadRequestError("Failed to update user.", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return e.HttpContext.JSON(http.StatusOK, e.User)
|
return e.HttpContext.JSON(http.StatusOK, e.User)
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
if handlerErr == nil {
|
if submitErr == nil {
|
||||||
api.app.OnUserAfterUpdateRequest().Trigger(event)
|
api.app.OnUserAfterUpdateRequest().Trigger(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
return handlerErr
|
return submitErr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *userApi) delete(c echo.Context) error {
|
func (api *userApi) delete(c echo.Context) error {
|
||||||
|
|
|
@ -748,9 +748,6 @@ func TestUserCreate(t *testing.T) {
|
||||||
`"email":{"code":"validation_required"`,
|
`"email":{"code":"validation_required"`,
|
||||||
`"password":{"code":"validation_required"`,
|
`"password":{"code":"validation_required"`,
|
||||||
},
|
},
|
||||||
ExpectedEvents: map[string]int{
|
|
||||||
"OnUserBeforeCreateRequest": 1,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "invalid data",
|
Name: "invalid data",
|
||||||
|
@ -764,9 +761,6 @@ func TestUserCreate(t *testing.T) {
|
||||||
`"password":{"code":"validation_length_out_of_range"`,
|
`"password":{"code":"validation_length_out_of_range"`,
|
||||||
`"passwordConfirm":{"code":"validation_values_mismatch"`,
|
`"passwordConfirm":{"code":"validation_values_mismatch"`,
|
||||||
},
|
},
|
||||||
ExpectedEvents: map[string]int{
|
|
||||||
"OnUserBeforeCreateRequest": 1,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "valid data but with disabled email/pass auth",
|
Name: "valid data but with disabled email/pass auth",
|
||||||
|
@ -868,9 +862,6 @@ func TestUserUpdate(t *testing.T) {
|
||||||
`"data":{`,
|
`"data":{`,
|
||||||
`"email":{"code":"validation_user_email_exists"`,
|
`"email":{"code":"validation_user_email_exists"`,
|
||||||
},
|
},
|
||||||
ExpectedEvents: map[string]int{
|
|
||||||
"OnUserBeforeUpdateRequest": 1,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "authorized as admin - valid data",
|
Name: "authorized as admin - valid data",
|
||||||
|
|
|
@ -74,8 +74,11 @@ func (form *AdminUpsert) checkUniqueEmail(value any) error {
|
||||||
return validation.NewError("validation_admin_email_exists", "Admin email already exists.")
|
return validation.NewError("validation_admin_email_exists", "Admin email already exists.")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Submit validates the form and upserts the form's admin model.
|
// Submit validates the form and upserts the form admin model.
|
||||||
func (form *AdminUpsert) Submit() error {
|
//
|
||||||
|
// You can optionally provide a list of InterceptorFunc to further
|
||||||
|
// modify the form behavior before persisting it.
|
||||||
|
func (form *AdminUpsert) Submit(interceptors ...InterceptorFunc) error {
|
||||||
if err := form.Validate(); err != nil {
|
if err := form.Validate(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -87,5 +90,7 @@ func (form *AdminUpsert) Submit() error {
|
||||||
form.admin.SetPassword(form.Password)
|
form.admin.SetPassword(form.Password)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return runInterceptors(func() error {
|
||||||
return form.app.Dao().SaveAdmin(form.admin)
|
return form.app.Dao().SaveAdmin(form.admin)
|
||||||
|
}, interceptors...)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package forms_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
validation "github.com/go-ozzo/ozzo-validation/v4"
|
validation "github.com/go-ozzo/ozzo-validation/v4"
|
||||||
|
@ -252,7 +253,14 @@ func TestAdminUpsertSubmit(t *testing.T) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
err := form.Submit()
|
interceptorCalls := 0
|
||||||
|
|
||||||
|
err := form.Submit(func(next forms.InterceptorNextFunc) forms.InterceptorNextFunc {
|
||||||
|
return func() error {
|
||||||
|
interceptorCalls++
|
||||||
|
return next()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
hasErr := err != nil
|
hasErr := err != nil
|
||||||
if hasErr != s.expectError {
|
if hasErr != s.expectError {
|
||||||
|
@ -266,6 +274,14 @@ func TestAdminUpsertSubmit(t *testing.T) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
expectInterceptorCall := 1
|
||||||
|
if s.expectError {
|
||||||
|
expectInterceptorCall = 0
|
||||||
|
}
|
||||||
|
if interceptorCalls != expectInterceptorCall {
|
||||||
|
t.Errorf("(%d) Expected interceptor to be called %d, got %d", i, expectInterceptorCall, interceptorCalls)
|
||||||
|
}
|
||||||
|
|
||||||
if s.expectError {
|
if s.expectError {
|
||||||
continue // skip persistence check
|
continue // skip persistence check
|
||||||
}
|
}
|
||||||
|
@ -283,3 +299,51 @@ func TestAdminUpsertSubmit(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAdminUpsertSubmitInterceptors(t *testing.T) {
|
||||||
|
app, _ := tests.NewTestApp()
|
||||||
|
defer app.Cleanup()
|
||||||
|
|
||||||
|
admin := &models.Admin{}
|
||||||
|
form := forms.NewAdminUpsert(app, admin)
|
||||||
|
form.Email = "test_new@example.com"
|
||||||
|
form.Password = "1234567890"
|
||||||
|
form.PasswordConfirm = form.Password
|
||||||
|
|
||||||
|
testErr := errors.New("test_error")
|
||||||
|
interceptorAdminEmail := ""
|
||||||
|
|
||||||
|
interceptor1Called := false
|
||||||
|
interceptor1 := func(next forms.InterceptorNextFunc) forms.InterceptorNextFunc {
|
||||||
|
return func() error {
|
||||||
|
interceptor1Called = true
|
||||||
|
return next()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interceptor2Called := false
|
||||||
|
interceptor2 := func(next forms.InterceptorNextFunc) forms.InterceptorNextFunc {
|
||||||
|
return func() error {
|
||||||
|
interceptorAdminEmail = admin.Email // to check if the record was filled
|
||||||
|
interceptor2Called = true
|
||||||
|
return testErr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err := form.Submit(interceptor1, interceptor2)
|
||||||
|
if err != testErr {
|
||||||
|
t.Fatalf("Expected error %v, got %v", testErr, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !interceptor1Called {
|
||||||
|
t.Fatalf("Expected interceptor1 to be called")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !interceptor2Called {
|
||||||
|
t.Fatalf("Expected interceptor2 to be called")
|
||||||
|
}
|
||||||
|
|
||||||
|
if interceptorAdminEmail != form.Email {
|
||||||
|
t.Fatalf("Expected the form model to be filled before calling the interceptors")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
// Package models implements various services used for request data
|
||||||
|
// validation and applying changes to existing DB models through the app Dao.
|
||||||
|
package forms
|
||||||
|
|
||||||
|
// InterceptorNextFunc is a interceptor handler function.
|
||||||
|
// Usually used in combination with InterceptorFunc.
|
||||||
|
type InterceptorNextFunc = func() error
|
||||||
|
|
||||||
|
// InterceptorFunc defines a single interceptor function that will execute the provided next func handler.
|
||||||
|
type InterceptorFunc func(next InterceptorNextFunc) InterceptorNextFunc
|
||||||
|
|
||||||
|
// runInterceptors executes the provided list of interceptors.
|
||||||
|
func runInterceptors(next InterceptorNextFunc, interceptors ...InterceptorFunc) error {
|
||||||
|
for i := len(interceptors) - 1; i >= 0; i-- {
|
||||||
|
next = interceptors[i](next)
|
||||||
|
}
|
||||||
|
|
||||||
|
return next()
|
||||||
|
}
|
|
@ -189,7 +189,10 @@ func (form *CollectionUpsert) checkRule(value any) error {
|
||||||
// Submit validates the form and upserts the form's Collection model.
|
// Submit validates the form and upserts the form's Collection model.
|
||||||
//
|
//
|
||||||
// On success the related record table schema will be auto updated.
|
// On success the related record table schema will be auto updated.
|
||||||
func (form *CollectionUpsert) Submit() error {
|
//
|
||||||
|
// You can optionally provide a list of InterceptorFunc to further
|
||||||
|
// modify the form behavior before persisting it.
|
||||||
|
func (form *CollectionUpsert) Submit(interceptors ...InterceptorFunc) error {
|
||||||
if err := form.Validate(); err != nil {
|
if err := form.Validate(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -211,5 +214,7 @@ func (form *CollectionUpsert) Submit() error {
|
||||||
form.collection.UpdateRule = form.UpdateRule
|
form.collection.UpdateRule = form.UpdateRule
|
||||||
form.collection.DeleteRule = form.DeleteRule
|
form.collection.DeleteRule = form.DeleteRule
|
||||||
|
|
||||||
|
return runInterceptors(func() error {
|
||||||
return form.app.Dao().SaveCollection(form.collection)
|
return form.app.Dao().SaveCollection(form.collection)
|
||||||
|
}, interceptors...)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package forms_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
validation "github.com/go-ozzo/ozzo-validation/v4"
|
validation "github.com/go-ozzo/ozzo-validation/v4"
|
||||||
|
@ -387,14 +388,31 @@ func TestCollectionUpsertSubmit(t *testing.T) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interceptorCalls := 0
|
||||||
|
interceptor := func(next forms.InterceptorNextFunc) forms.InterceptorNextFunc {
|
||||||
|
return func() error {
|
||||||
|
interceptorCalls++
|
||||||
|
return next()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// parse errors
|
// parse errors
|
||||||
result := form.Submit()
|
result := form.Submit(interceptor)
|
||||||
errs, ok := result.(validation.Errors)
|
errs, ok := result.(validation.Errors)
|
||||||
if !ok && result != nil {
|
if !ok && result != nil {
|
||||||
t.Errorf("(%d) Failed to parse errors %v", i, result)
|
t.Errorf("(%d) Failed to parse errors %v", i, result)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check interceptor calls
|
||||||
|
expectInterceptorCall := 1
|
||||||
|
if len(s.expectedErrors) > 0 {
|
||||||
|
expectInterceptorCall = 0
|
||||||
|
}
|
||||||
|
if interceptorCalls != expectInterceptorCall {
|
||||||
|
t.Errorf("(%d) Expected interceptor to be called %d, got %d", i, expectInterceptorCall, interceptorCalls)
|
||||||
|
}
|
||||||
|
|
||||||
// check errors
|
// check errors
|
||||||
if len(errs) > len(s.expectedErrors) {
|
if len(errs) > len(s.expectedErrors) {
|
||||||
t.Errorf("(%d) Expected error keys %v, got %v", i, s.expectedErrors, errs)
|
t.Errorf("(%d) Expected error keys %v, got %v", i, s.expectedErrors, errs)
|
||||||
|
@ -450,3 +468,53 @@ func TestCollectionUpsertSubmit(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCollectionUpsertSubmitInterceptors(t *testing.T) {
|
||||||
|
app, _ := tests.NewTestApp()
|
||||||
|
defer app.Cleanup()
|
||||||
|
|
||||||
|
collection, err := app.Dao().FindCollectionByNameOrId("demo")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
form := forms.NewCollectionUpsert(app, collection)
|
||||||
|
form.Name = "test_new"
|
||||||
|
|
||||||
|
testErr := errors.New("test_error")
|
||||||
|
interceptorCollectionName := ""
|
||||||
|
|
||||||
|
interceptor1Called := false
|
||||||
|
interceptor1 := func(next forms.InterceptorNextFunc) forms.InterceptorNextFunc {
|
||||||
|
return func() error {
|
||||||
|
interceptor1Called = true
|
||||||
|
return next()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interceptor2Called := false
|
||||||
|
interceptor2 := func(next forms.InterceptorNextFunc) forms.InterceptorNextFunc {
|
||||||
|
return func() error {
|
||||||
|
interceptorCollectionName = collection.Name // to check if the record was filled
|
||||||
|
interceptor2Called = true
|
||||||
|
return testErr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
submitErr := form.Submit(interceptor1, interceptor2)
|
||||||
|
if submitErr != testErr {
|
||||||
|
t.Fatalf("Expected submitError %v, got %v", testErr, submitErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !interceptor1Called {
|
||||||
|
t.Fatalf("Expected interceptor1 to be called")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !interceptor2Called {
|
||||||
|
t.Fatalf("Expected interceptor2 to be called")
|
||||||
|
}
|
||||||
|
|
||||||
|
if interceptorCollectionName != form.Name {
|
||||||
|
t.Fatalf("Expected the form model to be filled before calling the interceptors")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -271,7 +271,10 @@ func (form *RecordUpsert) DrySubmit(callback func(txDao *daos.Dao) error) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// Submit validates the form and upserts the form Record model.
|
// Submit validates the form and upserts the form Record model.
|
||||||
func (form *RecordUpsert) Submit() error {
|
//
|
||||||
|
// You can optionally provide a list of InterceptorFunc to further
|
||||||
|
// modify the form behavior before persisting it.
|
||||||
|
func (form *RecordUpsert) Submit(interceptors ...InterceptorFunc) error {
|
||||||
if err := form.Validate(); err != nil {
|
if err := form.Validate(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -281,6 +284,7 @@ func (form *RecordUpsert) Submit() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return runInterceptors(func() error {
|
||||||
return form.app.Dao().RunInTransaction(func(txDao *daos.Dao) error {
|
return form.app.Dao().RunInTransaction(func(txDao *daos.Dao) error {
|
||||||
// persist record model
|
// persist record model
|
||||||
if err := txDao.SaveRecord(form.record); err != nil {
|
if err := txDao.SaveRecord(form.record); err != nil {
|
||||||
|
@ -300,6 +304,7 @@ func (form *RecordUpsert) Submit() error {
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
}, interceptors...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (form *RecordUpsert) processFilesToUpload() error {
|
func (form *RecordUpsert) processFilesToUpload() error {
|
||||||
|
|
|
@ -3,6 +3,7 @@ package forms_test
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
@ -400,13 +401,27 @@ func TestRecordUpsertSubmitFailure(t *testing.T) {
|
||||||
req.Header.Set(echo.HeaderContentType, mp.FormDataContentType())
|
req.Header.Set(echo.HeaderContentType, mp.FormDataContentType())
|
||||||
form.LoadData(req)
|
form.LoadData(req)
|
||||||
|
|
||||||
|
interceptorCalls := 0
|
||||||
|
interceptor := func(next forms.InterceptorNextFunc) forms.InterceptorNextFunc {
|
||||||
|
return func() error {
|
||||||
|
interceptorCalls++
|
||||||
|
return next()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ensure that validate is triggered
|
// ensure that validate is triggered
|
||||||
// ---
|
// ---
|
||||||
result := form.Submit()
|
result := form.Submit(interceptor)
|
||||||
if result == nil {
|
if result == nil {
|
||||||
t.Fatal("Expected error, got nil")
|
t.Fatal("Expected error, got nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check interceptor calls
|
||||||
|
// ---
|
||||||
|
if interceptorCalls != 0 {
|
||||||
|
t.Fatalf("Expected interceptor to be called 0 times, got %d", interceptorCalls)
|
||||||
|
}
|
||||||
|
|
||||||
// ensure that the record changes weren't persisted
|
// ensure that the record changes weren't persisted
|
||||||
// ---
|
// ---
|
||||||
recordAfter, err := app.Dao().FindFirstRecordByData(collection, "id", recordBefore.Id)
|
recordAfter, err := app.Dao().FindFirstRecordByData(collection, "id", recordBefore.Id)
|
||||||
|
@ -451,11 +466,25 @@ func TestRecordUpsertSubmitSuccess(t *testing.T) {
|
||||||
req.Header.Set(echo.HeaderContentType, mp.FormDataContentType())
|
req.Header.Set(echo.HeaderContentType, mp.FormDataContentType())
|
||||||
form.LoadData(req)
|
form.LoadData(req)
|
||||||
|
|
||||||
result := form.Submit()
|
interceptorCalls := 0
|
||||||
|
interceptor := func(next forms.InterceptorNextFunc) forms.InterceptorNextFunc {
|
||||||
|
return func() error {
|
||||||
|
interceptorCalls++
|
||||||
|
return next()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result := form.Submit(interceptor)
|
||||||
if result != nil {
|
if result != nil {
|
||||||
t.Fatalf("Expected nil, got error %v", result)
|
t.Fatalf("Expected nil, got error %v", result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check interceptor calls
|
||||||
|
// ---
|
||||||
|
if interceptorCalls != 1 {
|
||||||
|
t.Fatalf("Expected interceptor to be called 1 time, got %d", interceptorCalls)
|
||||||
|
}
|
||||||
|
|
||||||
// ensure that the record changes were persisted
|
// ensure that the record changes were persisted
|
||||||
// ---
|
// ---
|
||||||
recordAfter, err := app.Dao().FindFirstRecordByData(collection, "id", recordBefore.Id)
|
recordAfter, err := app.Dao().FindFirstRecordByData(collection, "id", recordBefore.Id)
|
||||||
|
@ -482,6 +511,57 @@ func TestRecordUpsertSubmitSuccess(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRecordUpsertSubmitInterceptors(t *testing.T) {
|
||||||
|
app, _ := tests.NewTestApp()
|
||||||
|
defer app.Cleanup()
|
||||||
|
|
||||||
|
collection, _ := app.Dao().FindCollectionByNameOrId("demo4")
|
||||||
|
record, err := app.Dao().FindFirstRecordByData(collection, "id", "054f9f24-0a0a-4e09-87b1-bc7ff2b336a2")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
form := forms.NewRecordUpsert(app, record)
|
||||||
|
form.Data["title"] = "test_new"
|
||||||
|
|
||||||
|
testErr := errors.New("test_error")
|
||||||
|
interceptorRecordTitle := ""
|
||||||
|
|
||||||
|
interceptor1Called := false
|
||||||
|
interceptor1 := func(next forms.InterceptorNextFunc) forms.InterceptorNextFunc {
|
||||||
|
return func() error {
|
||||||
|
interceptor1Called = true
|
||||||
|
return next()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interceptor2Called := false
|
||||||
|
interceptor2 := func(next forms.InterceptorNextFunc) forms.InterceptorNextFunc {
|
||||||
|
return func() error {
|
||||||
|
interceptorRecordTitle = record.GetStringDataValue("title") // to check if the record was filled
|
||||||
|
interceptor2Called = true
|
||||||
|
return testErr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
submitErr := form.Submit(interceptor1, interceptor2)
|
||||||
|
if submitErr != testErr {
|
||||||
|
t.Fatalf("Expected submitError %v, got %v", testErr, submitErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !interceptor1Called {
|
||||||
|
t.Fatalf("Expected interceptor1 to be called")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !interceptor2Called {
|
||||||
|
t.Fatalf("Expected interceptor2 to be called")
|
||||||
|
}
|
||||||
|
|
||||||
|
if interceptorRecordTitle != form.Data["title"].(string) {
|
||||||
|
t.Fatalf("Expected the form model to be filled before calling the interceptors")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func hasRecordFile(app core.App, record *models.Record, filename string) bool {
|
func hasRecordFile(app core.App, record *models.Record, filename string) bool {
|
||||||
fs, _ := app.NewFilesystem()
|
fs, _ := app.NewFilesystem()
|
||||||
defer fs.Close()
|
defer fs.Close()
|
||||||
|
|
|
@ -33,13 +33,17 @@ func (form *SettingsUpsert) Validate() error {
|
||||||
// Submit validates the form and upserts the loaded settings.
|
// Submit validates the form and upserts the loaded settings.
|
||||||
//
|
//
|
||||||
// On success the app settings will be refreshed with the form ones.
|
// On success the app settings will be refreshed with the form ones.
|
||||||
func (form *SettingsUpsert) Submit() error {
|
//
|
||||||
|
// You can optionally provide a list of InterceptorFunc to further
|
||||||
|
// modify the form behavior before persisting it.
|
||||||
|
func (form *SettingsUpsert) Submit(interceptors ...InterceptorFunc) error {
|
||||||
if err := form.Validate(); err != nil {
|
if err := form.Validate(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
encryptionKey := os.Getenv(form.app.EncryptionEnv())
|
encryptionKey := os.Getenv(form.app.EncryptionEnv())
|
||||||
|
|
||||||
|
return runInterceptors(func() error {
|
||||||
saveErr := form.app.Dao().SaveParam(
|
saveErr := form.app.Dao().SaveParam(
|
||||||
models.ParamAppSettings,
|
models.ParamAppSettings,
|
||||||
form.Settings,
|
form.Settings,
|
||||||
|
@ -56,4 +60,5 @@ func (form *SettingsUpsert) Submit() error {
|
||||||
|
|
||||||
// merge the application settings with the form ones
|
// merge the application settings with the form ones
|
||||||
return form.app.Settings().Merge(form.Settings)
|
return form.app.Settings().Merge(form.Settings)
|
||||||
|
}, interceptors...)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package forms_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
@ -98,14 +99,31 @@ func TestSettingsUpsertSubmit(t *testing.T) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interceptorCalls := 0
|
||||||
|
interceptor := func(next forms.InterceptorNextFunc) forms.InterceptorNextFunc {
|
||||||
|
return func() error {
|
||||||
|
interceptorCalls++
|
||||||
|
return next()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// parse errors
|
// parse errors
|
||||||
result := form.Submit()
|
result := form.Submit(interceptor)
|
||||||
errs, ok := result.(validation.Errors)
|
errs, ok := result.(validation.Errors)
|
||||||
if !ok && result != nil {
|
if !ok && result != nil {
|
||||||
t.Errorf("(%d) Failed to parse errors %v", i, result)
|
t.Errorf("(%d) Failed to parse errors %v", i, result)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check interceptor calls
|
||||||
|
expectInterceptorCall := 1
|
||||||
|
if len(s.expectedErrors) > 0 {
|
||||||
|
expectInterceptorCall = 0
|
||||||
|
}
|
||||||
|
if interceptorCalls != expectInterceptorCall {
|
||||||
|
t.Errorf("(%d) Expected interceptor to be called %d, got %d", i, expectInterceptorCall, interceptorCalls)
|
||||||
|
}
|
||||||
|
|
||||||
// check errors
|
// check errors
|
||||||
if len(errs) > len(s.expectedErrors) {
|
if len(errs) > len(s.expectedErrors) {
|
||||||
t.Errorf("(%d) Expected error keys %v, got %v", i, s.expectedErrors, errs)
|
t.Errorf("(%d) Expected error keys %v, got %v", i, s.expectedErrors, errs)
|
||||||
|
@ -128,3 +146,42 @@ func TestSettingsUpsertSubmit(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSettingsUpsertSubmitInterceptors(t *testing.T) {
|
||||||
|
app, _ := tests.NewTestApp()
|
||||||
|
defer app.Cleanup()
|
||||||
|
|
||||||
|
form := forms.NewSettingsUpsert(app)
|
||||||
|
form.Meta.AppName = "test_new"
|
||||||
|
|
||||||
|
testErr := errors.New("test_error")
|
||||||
|
|
||||||
|
interceptor1Called := false
|
||||||
|
interceptor1 := func(next forms.InterceptorNextFunc) forms.InterceptorNextFunc {
|
||||||
|
return func() error {
|
||||||
|
interceptor1Called = true
|
||||||
|
return next()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interceptor2Called := false
|
||||||
|
interceptor2 := func(next forms.InterceptorNextFunc) forms.InterceptorNextFunc {
|
||||||
|
return func() error {
|
||||||
|
interceptor2Called = true
|
||||||
|
return testErr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
submitErr := form.Submit(interceptor1, interceptor2)
|
||||||
|
if submitErr != testErr {
|
||||||
|
t.Fatalf("Expected submitError %v, got %v", testErr, submitErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !interceptor1Called {
|
||||||
|
t.Fatalf("Expected interceptor1 to be called")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !interceptor2Called {
|
||||||
|
t.Fatalf("Expected interceptor2 to be called")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -98,7 +98,10 @@ func (form *UserUpsert) checkEmailDomain(value any) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Submit validates the form and upserts the form user model.
|
// Submit validates the form and upserts the form user model.
|
||||||
func (form *UserUpsert) Submit() error {
|
//
|
||||||
|
// You can optionally provide a list of InterceptorFunc to further
|
||||||
|
// modify the form behavior before persisting it.
|
||||||
|
func (form *UserUpsert) Submit(interceptors ...InterceptorFunc) error {
|
||||||
if err := form.Validate(); err != nil {
|
if err := form.Validate(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -114,5 +117,7 @@ func (form *UserUpsert) Submit() error {
|
||||||
|
|
||||||
form.user.Email = form.Email
|
form.user.Email = form.Email
|
||||||
|
|
||||||
|
return runInterceptors(func() error {
|
||||||
return form.app.Dao().SaveUser(form.user)
|
return form.app.Dao().SaveUser(form.user)
|
||||||
|
}, interceptors...)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package forms_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
validation "github.com/go-ozzo/ozzo-validation/v4"
|
validation "github.com/go-ozzo/ozzo-validation/v4"
|
||||||
|
@ -212,13 +213,28 @@ func TestUserUpsertSubmit(t *testing.T) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
err := form.Submit()
|
interceptorCalls := 0
|
||||||
|
|
||||||
|
err := form.Submit(func(next forms.InterceptorNextFunc) forms.InterceptorNextFunc {
|
||||||
|
return func() error {
|
||||||
|
interceptorCalls++
|
||||||
|
return next()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
hasErr := err != nil
|
hasErr := err != nil
|
||||||
if hasErr != s.expectError {
|
if hasErr != s.expectError {
|
||||||
t.Errorf("(%d) Expected hasErr to be %v, got %v (%v)", i, s.expectError, hasErr, err)
|
t.Errorf("(%d) Expected hasErr to be %v, got %v (%v)", i, s.expectError, hasErr, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
expectInterceptorCall := 1
|
||||||
|
if s.expectError {
|
||||||
|
expectInterceptorCall = 0
|
||||||
|
}
|
||||||
|
if interceptorCalls != expectInterceptorCall {
|
||||||
|
t.Errorf("(%d) Expected interceptor to be called %d, got %d", i, expectInterceptorCall, interceptorCalls)
|
||||||
|
}
|
||||||
|
|
||||||
if s.expectError {
|
if s.expectError {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -240,3 +256,51 @@ func TestUserUpsertSubmit(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestUserUpsertSubmitInterceptors(t *testing.T) {
|
||||||
|
app, _ := tests.NewTestApp()
|
||||||
|
defer app.Cleanup()
|
||||||
|
|
||||||
|
user := &models.User{}
|
||||||
|
form := forms.NewUserUpsert(app, user)
|
||||||
|
form.Email = "test_new@example.com"
|
||||||
|
form.Password = "1234567890"
|
||||||
|
form.PasswordConfirm = form.Password
|
||||||
|
|
||||||
|
testErr := errors.New("test_error")
|
||||||
|
interceptorUserEmail := ""
|
||||||
|
|
||||||
|
interceptor1Called := false
|
||||||
|
interceptor1 := func(next forms.InterceptorNextFunc) forms.InterceptorNextFunc {
|
||||||
|
return func() error {
|
||||||
|
interceptor1Called = true
|
||||||
|
return next()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interceptor2Called := false
|
||||||
|
interceptor2 := func(next forms.InterceptorNextFunc) forms.InterceptorNextFunc {
|
||||||
|
return func() error {
|
||||||
|
interceptorUserEmail = user.Email // to check if the record was filled
|
||||||
|
interceptor2Called = true
|
||||||
|
return testErr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err := form.Submit(interceptor1, interceptor2)
|
||||||
|
if err != testErr {
|
||||||
|
t.Fatalf("Expected error %v, got %v", testErr, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !interceptor1Called {
|
||||||
|
t.Fatalf("Expected interceptor1 to be called")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !interceptor2Called {
|
||||||
|
t.Fatalf("Expected interceptor2 to be called")
|
||||||
|
}
|
||||||
|
|
||||||
|
if interceptorUserEmail != form.Email {
|
||||||
|
t.Fatalf("Expected the form model to be filled before calling the interceptors")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue