mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2024-11-25 13:16:40 +00:00
Compare commits
2 commits
e2af3cf510
...
7670a7d964
Author | SHA1 | Date | |
---|---|---|---|
7670a7d964 | |||
0e910d733d |
|
@ -18,7 +18,10 @@
|
||||||
package v2
|
package v2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
@ -180,12 +183,43 @@ func (m *Module) FilterPUTHandler(c *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the request is JSON:
|
||||||
|
// Explicitly check whether `expires_in` is a null literal (vs. not being set at all).
|
||||||
|
hasNullExpiresIn := false
|
||||||
|
if c.ContentType() == gin.MIMEJSON {
|
||||||
|
// To do this, we need to read the request body twice, once here and once below for the form, so we buffer it.
|
||||||
|
// If a filter update request is bigger than a megabyte, somebody's messing with us.
|
||||||
|
bodyBytes, err := io.ReadAll(io.LimitReader(c.Request.Body, 1024*1024))
|
||||||
|
if err != nil {
|
||||||
|
apiutil.ErrorHandler(c, gtserror.NewErrorBadRequest(err, err.Error()), m.processor.InstanceGetV1)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.Request.Body = io.NopCloser(bytes.NewReader(bodyBytes))
|
||||||
|
|
||||||
|
// Partially parse the body as a JSON object.
|
||||||
|
requestJSONObject := map[string]json.RawMessage{}
|
||||||
|
if err := json.Unmarshal(bodyBytes, &requestJSONObject); err != nil {
|
||||||
|
apiutil.ErrorHandler(c, gtserror.NewErrorBadRequest(err, err.Error()), m.processor.InstanceGetV1)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to parse the `expires_in` field as a literal null.
|
||||||
|
if raw, found := requestJSONObject["expires_in"]; found {
|
||||||
|
hasNullExpiresIn = string(raw) == "null"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
form := &apimodel.FilterUpdateRequestV2{}
|
form := &apimodel.FilterUpdateRequestV2{}
|
||||||
if err := c.ShouldBind(form); err != nil {
|
if err := c.ShouldBind(form); err != nil {
|
||||||
apiutil.ErrorHandler(c, gtserror.NewErrorBadRequest(err, err.Error()), m.processor.InstanceGetV1)
|
apiutil.ErrorHandler(c, gtserror.NewErrorBadRequest(err, err.Error()), m.processor.InstanceGetV1)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Interpret a literal null `expires_in` as unsetting the expiration date.
|
||||||
|
if hasNullExpiresIn {
|
||||||
|
form.ExpiresIn = util.Ptr(0)
|
||||||
|
}
|
||||||
|
|
||||||
if err := validateNormalizeUpdateFilter(form); err != nil {
|
if err := validateNormalizeUpdateFilter(form); err != nil {
|
||||||
apiutil.ErrorHandler(c, gtserror.NewErrorUnprocessableEntity(err, err.Error()), m.processor.InstanceGetV1)
|
apiutil.ErrorHandler(c, gtserror.NewErrorUnprocessableEntity(err, err.Error()), m.processor.InstanceGetV1)
|
||||||
return
|
return
|
||||||
|
@ -283,11 +317,6 @@ func validateNormalizeUpdateFilter(form *apimodel.FilterUpdateRequestV2) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Interpret zero as indefinite duration.
|
|
||||||
if form.ExpiresIn != nil && *form.ExpiresIn == 0 {
|
|
||||||
form.ExpiresIn = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Normalize and validate updates.
|
// Normalize and validate updates.
|
||||||
for i, formKeyword := range form.Keywords {
|
for i, formKeyword := range form.Keywords {
|
||||||
if formKeyword.Keyword != nil {
|
if formKeyword.Keyword != nil {
|
||||||
|
|
|
@ -394,3 +394,20 @@ func (suite *FiltersTestSuite) TestPutFilterUnsetExpirationDateNullJSON() {
|
||||||
filter = suite.setFilterExpiration(id, nil, nil, &requestJson)
|
filter = suite.setFilterExpiration(id, nil, nil, &requestJson)
|
||||||
suite.Nil(filter.ExpiresAt)
|
suite.Nil(filter.ExpiresAt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Regression test related to https://github.com/superseriousbusiness/gotosocial/issues/3497
|
||||||
|
func (suite *FiltersTestSuite) TestPutFilterUnalteredExpirationDateJSON() {
|
||||||
|
id := suite.testFilters["local_account_1_filter_4"].ID
|
||||||
|
|
||||||
|
// Setup: set an expiration date for the filter.
|
||||||
|
expiresIn := 86400
|
||||||
|
filter := suite.setFilterExpiration(id, &expiresIn, nil, nil)
|
||||||
|
if !suite.NotNil(filter.ExpiresAt) {
|
||||||
|
suite.FailNow("Test precondition failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update nothing. There should still be an expiration date.
|
||||||
|
requestJson := `{}`
|
||||||
|
filter = suite.setFilterExpiration(id, nil, nil, &requestJson)
|
||||||
|
suite.NotNil(filter.ExpiresAt)
|
||||||
|
}
|
||||||
|
|
|
@ -21,8 +21,6 @@
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
|
||||||
|
|
||||||
apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
|
apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/db"
|
"github.com/superseriousbusiness/gotosocial/internal/db"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
|
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
|
||||||
|
@ -30,6 +28,7 @@
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/id"
|
"github.com/superseriousbusiness/gotosocial/internal/id"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/typeutils"
|
"github.com/superseriousbusiness/gotosocial/internal/typeutils"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/util"
|
"github.com/superseriousbusiness/gotosocial/internal/util"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Update an existing filter for the given account, using the provided parameters.
|
// Update an existing filter for the given account, using the provided parameters.
|
||||||
|
@ -68,10 +67,16 @@ func (p *Processor) Update(
|
||||||
filterColumns = append(filterColumns, "action")
|
filterColumns = append(filterColumns, "action")
|
||||||
filter.Action = typeutils.APIFilterActionToFilterAction(*form.FilterAction)
|
filter.Action = typeutils.APIFilterActionToFilterAction(*form.FilterAction)
|
||||||
}
|
}
|
||||||
// TODO: (Vyr) is it possible to unset a filter expiration with this API?
|
|
||||||
if form.ExpiresIn != nil {
|
if form.ExpiresIn != nil {
|
||||||
|
expiresIn := *form.ExpiresIn
|
||||||
filterColumns = append(filterColumns, "expires_at")
|
filterColumns = append(filterColumns, "expires_at")
|
||||||
filter.ExpiresAt = time.Now().Add(time.Second * time.Duration(*form.ExpiresIn))
|
if expiresIn == 0 {
|
||||||
|
// Unset the expiration date.
|
||||||
|
filter.ExpiresAt = time.Time{}
|
||||||
|
} else {
|
||||||
|
// Update the expiration date.
|
||||||
|
filter.ExpiresAt = time.Now().Add(time.Second * time.Duration(expiresIn))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if form.Context != nil {
|
if form.Context != nil {
|
||||||
filterColumns = append(filterColumns,
|
filterColumns = append(filterColumns,
|
||||||
|
|
Loading…
Reference in a new issue