2021-05-10 16:29:05 +02:00
/ *
GoToSocial
Copyright ( C ) 2021 GoToSocial Authors admin @ gotosocial . org
This program is free software : you can redistribute it and / or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation , either version 3 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU Affero General Public License for more details .
You should have received a copy of the GNU Affero General Public License
along with this program . If not , see < http : //www.gnu.org/licenses/>.
* /
2021-08-02 19:06:44 +02:00
package media
import (
"errors"
"fmt"
"net/http"
2021-12-07 13:31:39 +01:00
"github.com/sirupsen/logrus"
"github.com/spf13/viper"
2021-08-02 19:06:44 +02:00
"github.com/gin-gonic/gin"
2021-12-11 17:50:00 +01:00
"github.com/superseriousbusiness/gotosocial/internal/api"
2021-08-02 19:06:44 +02:00
"github.com/superseriousbusiness/gotosocial/internal/api/model"
"github.com/superseriousbusiness/gotosocial/internal/config"
"github.com/superseriousbusiness/gotosocial/internal/oauth"
)
// MediaPUTHandler swagger:operation PUT /api/v1/media/{id} mediaUpdate
//
// Update a media attachment.
//
// You must own the media attachment, and the attachment must not yet be attached to a status.
//
// The parameters can also be given in the body of the request, as JSON, if the content-type is set to 'application/json'.
// The parameters can also be given in the body of the request, as XML, if the content-type is set to 'application/xml'.
//
// ---
// tags:
// - media
//
// consumes:
// - application/json
// - application/xml
// - application/x-www-form-urlencoded
//
// produces:
// - application/json
//
// parameters:
// - name: id
// description: id of the attachment to update
// type: string
// in: path
// required: true
// - name: description
// in: formData
// description: |-
// Image or media description to use as alt-text on the attachment.
// This is very useful for users of screenreaders.
// May or may not be required, depending on your instance settings.
// type: string
// allowEmptyValue: true
// - name: focus
// in: formData
// description: |-
// Focus of the media file.
// If present, it should be in the form of two comma-separated floats between -1 and 1.
// For example: `-0.5,0.25`.
// type: string
// allowEmptyValue: true
//
// security:
// - OAuth2 Bearer:
// - write:media
//
// responses:
// '200':
// description: The newly-updated media attachment.
// schema:
// "$ref": "#/definitions/attachment"
// '400':
// description: bad request
// '401':
// description: unauthorized
// '403':
// description: forbidden
// '422':
// description: unprocessable
2021-05-10 16:29:05 +02:00
func ( m * Module ) MediaPUTHandler ( c * gin . Context ) {
2021-10-11 14:37:33 +02:00
l := logrus . WithField ( "func" , "MediaGETHandler" )
2021-05-10 16:29:05 +02:00
authed , err := oauth . Authed ( c , true , true , true , true )
if err != nil {
l . Debugf ( "couldn't auth: %s" , err )
c . JSON ( http . StatusForbidden , gin . H { "error" : err . Error ( ) } )
return
}
2021-12-11 17:50:00 +01:00
if _ , err := api . NegotiateAccept ( c , api . JSONAcceptHeaders ... ) ; err != nil {
c . JSON ( http . StatusNotAcceptable , gin . H { "error" : err . Error ( ) } )
return
}
2021-05-10 16:29:05 +02:00
attachmentID := c . Param ( IDKey )
if attachmentID == "" {
c . JSON ( http . StatusBadRequest , gin . H { "error" : "no attachment ID given in request" } )
return
}
// extract the media update form from the request context
l . Tracef ( "parsing request form: %s" , c . Request . Form )
var form model . AttachmentUpdateRequest
if err := c . ShouldBind ( & form ) ; err != nil {
l . Debugf ( "could not parse form from request: %s" , err )
c . JSON ( http . StatusBadRequest , gin . H { "error" : "missing one or more required form values" } )
return
}
// Give the fields on the request form a first pass to make sure the request is superficially valid.
l . Tracef ( "validating form %+v" , form )
2021-12-07 13:31:39 +01:00
if err := validateUpdateMedia ( & form ) ; err != nil {
2021-05-10 16:29:05 +02:00
l . Debugf ( "error validating form: %s" , err )
c . JSON ( http . StatusBadRequest , gin . H { "error" : err . Error ( ) } )
return
}
2021-08-25 15:34:33 +02:00
attachment , errWithCode := m . processor . MediaUpdate ( c . Request . Context ( ) , authed , attachmentID , & form )
2021-05-10 16:29:05 +02:00
if errWithCode != nil {
c . JSON ( errWithCode . Code ( ) , gin . H { "error" : errWithCode . Safe ( ) } )
return
}
c . JSON ( http . StatusOK , attachment )
}
2021-12-07 13:31:39 +01:00
func validateUpdateMedia ( form * model . AttachmentUpdateRequest ) error {
keys := config . Keys
minDescriptionChars := viper . GetInt ( keys . MediaDescriptionMinChars )
maxDescriptionChars := viper . GetInt ( keys . MediaDescriptionMaxChars )
2021-05-10 16:29:05 +02:00
if form . Description != nil {
2021-12-07 13:31:39 +01:00
if len ( * form . Description ) < minDescriptionChars || len ( * form . Description ) > maxDescriptionChars {
return fmt . Errorf ( "image description length must be between %d and %d characters (inclusive), but provided image description was %d chars" , minDescriptionChars , maxDescriptionChars , len ( * form . Description ) )
2021-05-10 16:29:05 +02:00
}
}
if form . Focus == nil && form . Description == nil {
return errors . New ( "focus and description were both nil, there's nothing to update" )
}
return nil
}