[feature] Add support for profile fields (#1483)

* Add go-playground/form pkg

* [feature] Add support for profile fields

* Add field attributes test

* Validate profile fields form

* Add profile field validation tests

* Add Field Attributes definition to swagger

---------

Co-authored-by: tobi <31960611+tsmethurst@users.noreply.github.com>
This commit is contained in:
zowhoey
2023-03-06 09:30:19 +00:00
committed by GitHub
parent 24f6a447f3
commit f518f649f8
21 changed files with 2399 additions and 2 deletions

View File

@@ -25,6 +25,7 @@ import (
"strconv"
"github.com/gin-gonic/gin"
"github.com/go-playground/form/v4"
apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
apiutil "github.com/superseriousbusiness/gotosocial/internal/api/util"
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
@@ -115,6 +116,13 @@ import (
// in: formData
// description: Enable RSS feed for this account's Public posts at `/[username]/feed.rss`
// type: boolean
// -
// name: fields_attributes
// in: formData
// description: Profile fields to be added to this account's profile
// type: array
// items:
// type: object
//
// security:
// - OAuth2 Bearer:
@@ -162,6 +170,28 @@ func (m *Module) AccountUpdateCredentialsPATCHHandler(c *gin.Context) {
c.JSON(http.StatusOK, acctSensitive)
}
type fieldAttributesBinding struct{}
func (fieldAttributesBinding) Name() string {
return "FieldAttributes"
}
func (fieldAttributesBinding) Bind(req *http.Request, obj any) error {
if err := req.ParseForm(); err != nil {
return err
}
decoder := form.NewDecoder()
// change default namespace prefix and suffix to allow correct parsing of the field attributes
decoder.SetNamespacePrefix("[")
decoder.SetNamespaceSuffix("]")
if err := decoder.Decode(obj, req.Form); err != nil {
return err
}
return nil
}
func parseUpdateAccountForm(c *gin.Context) (*apimodel.UpdateCredentialsRequest, error) {
form := &apimodel.UpdateCredentialsRequest{
Source: &apimodel.UpdateSource{},
@@ -171,6 +201,11 @@ func parseUpdateAccountForm(c *gin.Context) (*apimodel.UpdateCredentialsRequest,
return nil, fmt.Errorf("could not parse form from request: %s", err)
}
// use custom form binding to support field attributes in the form data
if err := c.ShouldBindWith(&form, fieldAttributesBinding{}); err != nil {
return nil, fmt.Errorf("could not parse form from request: %s", err)
}
// parse source field-by-field
sourceMap := c.PostFormMap("source")

View File

@@ -38,12 +38,14 @@ type AccountUpdateTestSuite struct {
func (suite *AccountUpdateTestSuite) TestAccountUpdateCredentialsPATCHHandler() {
// set up the request
// we're updating the note of zork
// we're updating the note and profile fields of zork
newBio := "this is my new bio read it and weep"
requestBody, w, err := testrig.CreateMultipartFormData(
"", "",
map[string]string{
"note": newBio,
"note": newBio,
"fields_attributes[0][name]": "pronouns",
"fields_attributes[0][value]": "they/them",
})
if err != nil {
panic(err)
@@ -74,6 +76,7 @@ func (suite *AccountUpdateTestSuite) TestAccountUpdateCredentialsPATCHHandler()
// check the returned api model account
// fields should be updated
suite.Equal("<p>this is my new bio read it and weep</p>", apimodelAccount.Note)
suite.Equal("they/them", apimodelAccount.Fields[0].Value)
suite.Equal(newBio, apimodelAccount.Source.Note)
}