[feature] Add emoji DELETE handler at /api/v1/admin/custom_emojis (#913)

* add emoji DELETE handler

* no need to process error (thanks kim)

* don't double check if user is admin

* add missing security annotation
This commit is contained in:
tobi
2022-10-14 17:30:04 +02:00
committed by GitHub
parent 6a95f5fa67
commit f7416d6e94
11 changed files with 369 additions and 0 deletions

View File

@ -0,0 +1,110 @@
/*
GoToSocial
Copyright (C) 2021-2022 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/>.
*/
package admin
import (
"errors"
"fmt"
"net/http"
"github.com/gin-gonic/gin"
"github.com/superseriousbusiness/gotosocial/internal/api"
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
"github.com/superseriousbusiness/gotosocial/internal/oauth"
)
// EmojiDELETEHandler swagger:operation DELETE /api/v1/admin/custom_emojis/{id} emojiDelete
//
// Delete a **local** emoji with the given ID from the instance.
//
// Emoji with the given ID will no longer be available to use on the instance.
//
// If you just want to update the emoji image instead, use the `/api/v1/admin/custom_emojis/{id}` PATCH route.
//
// To disable emojis from **remote** instances, use the `/api/v1/admin/custom_emojis/{id}` PATCH route.
//
// ---
// tags:
// - admin
//
// produces:
// - application/json
//
// parameters:
// -
// name: id
// type: string
// description: The id of the emoji.
// in: path
// required: true
//
// security:
// - OAuth2 Bearer:
// - admin
//
// responses:
// '200':
// description: The deleted emoji will be returned to the caller in case further processing is necessary.
// schema:
// "$ref": "#/definitions/adminEmoji"
// '400':
// description: bad request
// '401':
// description: unauthorized
// '403':
// description: forbidden
// '404':
// description: not found
// '406':
// description: not acceptable
// '500':
// description: internal server error
func (m *Module) EmojiDELETEHandler(c *gin.Context) {
authed, err := oauth.Authed(c, true, true, true, true)
if err != nil {
api.ErrorHandler(c, gtserror.NewErrorUnauthorized(err, err.Error()), m.processor.InstanceGet)
return
}
if !*authed.User.Admin {
err := fmt.Errorf("user %s not an admin", authed.User.ID)
api.ErrorHandler(c, gtserror.NewErrorForbidden(err, err.Error()), m.processor.InstanceGet)
return
}
if _, err := api.NegotiateAccept(c, api.JSONAcceptHeaders...); err != nil {
api.ErrorHandler(c, gtserror.NewErrorNotAcceptable(err, err.Error()), m.processor.InstanceGet)
return
}
emojiID := c.Param(IDKey)
if emojiID == "" {
err := errors.New("no emoji id specified")
api.ErrorHandler(c, gtserror.NewErrorBadRequest(err, err.Error()), m.processor.InstanceGet)
return
}
emoji, errWithCode := m.processor.AdminEmojiDelete(c.Request.Context(), authed, emojiID)
if errWithCode != nil {
api.ErrorHandler(c, errWithCode, m.processor.InstanceGet)
return
}
c.JSON(http.StatusOK, emoji)
}

View File

@ -0,0 +1,101 @@
/*
GoToSocial
Copyright (C) 2021-2022 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/>.
*/
package admin_test
import (
"context"
"io"
"net/http"
"net/http/httptest"
"testing"
"github.com/stretchr/testify/suite"
"github.com/superseriousbusiness/gotosocial/internal/api/client/admin"
"github.com/superseriousbusiness/gotosocial/internal/db"
)
type EmojiDeleteTestSuite struct {
AdminStandardTestSuite
}
func (suite *EmojiDeleteTestSuite) TestEmojiDelete1() {
recorder := httptest.NewRecorder()
testEmoji := suite.testEmojis["rainbow"]
path := admin.EmojiPathWithID
ctx := suite.newContext(recorder, http.MethodDelete, nil, path, "application/json")
ctx.AddParam(admin.IDKey, testEmoji.ID)
suite.adminModule.EmojiDELETEHandler(ctx)
suite.Equal(http.StatusOK, recorder.Code)
b, err := io.ReadAll(recorder.Body)
suite.NoError(err)
suite.NotNil(b)
suite.Equal(`{"shortcode":"rainbow","url":"http://localhost:8080/fileserver/01F8MH17FWEB39HZJ76B6VXSKF/emoji/original/01F8MH9H8E4VG3KDYJR9EGPXCQ.png","static_url":"http://localhost:8080/fileserver/01F8MH17FWEB39HZJ76B6VXSKF/emoji/static/01F8MH9H8E4VG3KDYJR9EGPXCQ.png","visible_in_picker":true,"id":"01F8MH9H8E4VG3KDYJR9EGPXCQ","disabled":false,"updated_at":"2021-09-20T10:40:37.000Z","total_file_size":47115,"content_type":"image/png","uri":"http://localhost:8080/emoji/01F8MH9H8E4VG3KDYJR9EGPXCQ"}`, string(b))
// emoji should no longer be in the db
dbEmoji, err := suite.db.GetEmojiByID(context.Background(), testEmoji.ID)
suite.Nil(dbEmoji)
suite.ErrorIs(err, db.ErrNoEntries)
}
func (suite *EmojiDeleteTestSuite) TestEmojiDelete2() {
recorder := httptest.NewRecorder()
testEmoji := suite.testEmojis["yell"]
path := admin.EmojiPathWithID
ctx := suite.newContext(recorder, http.MethodDelete, nil, path, "application/json")
ctx.AddParam(admin.IDKey, testEmoji.ID)
suite.adminModule.EmojiDELETEHandler(ctx)
suite.Equal(http.StatusBadRequest, recorder.Code)
b, err := io.ReadAll(recorder.Body)
suite.NoError(err)
suite.NotNil(b)
suite.Equal(`{"error":"Bad Request: EmojiDelete: emoji with id 01GD5KP5CQEE1R3X43Y1EHS2CW was not a local emoji, will not delete"}`, string(b))
// emoji should still be in the db
dbEmoji, err := suite.db.GetEmojiByID(context.Background(), testEmoji.ID)
suite.NoError(err)
suite.NotNil(dbEmoji)
}
func (suite *EmojiDeleteTestSuite) TestEmojiDeleteNotFound() {
recorder := httptest.NewRecorder()
path := admin.EmojiPathWithID
ctx := suite.newContext(recorder, http.MethodDelete, nil, path, "application/json")
ctx.AddParam(admin.IDKey, "01GF8VRXX1R00X7XH8973Z29R1")
suite.adminModule.EmojiDELETEHandler(ctx)
suite.Equal(http.StatusNotFound, recorder.Code)
b, err := io.ReadAll(recorder.Body)
suite.NoError(err)
suite.NotNil(b)
suite.Equal(`{"error":"Not Found"}`, string(b))
}
func TestEmojiDeleteTestSuite(t *testing.T) {
suite.Run(t, &EmojiDeleteTestSuite{})
}