get individual domain block, delete a block

This commit is contained in:
tsmethurst 2021-07-05 13:09:24 +02:00
commit 8475898b75
18 changed files with 213 additions and 16 deletions

View file

@ -35,9 +35,13 @@ const (
EmojiPath = BasePath + "/custom_emojis"
// DomainBlocksPath is used for posting domain blocks.
DomainBlocksPath = BasePath + "/domain_blocks"
// DomainBlockPath is used for interacting with a single domain block.
DomainBlockPath = DomainBlocksPath + "/:" + IDKey
// ExportQueryKey is the key to use when requesting a public export of some data.
// ExportQueryKey is for requesting a public export of some data.
ExportQueryKey = "export"
// IDKey specifies the ID of a single item being interacted with.
IDKey = "id"
)
// Module implements the ClientAPIModule interface for admin-related actions (reports, emojis, etc)
@ -61,5 +65,7 @@ func (m *Module) Route(r router.Router) error {
r.AttachHandler(http.MethodPost, EmojiPath, m.emojiCreatePOSTHandler)
r.AttachHandler(http.MethodPost, DomainBlocksPath, m.DomainBlocksPOSTHandler)
r.AttachHandler(http.MethodGet, DomainBlocksPath, m.DomainBlocksGETHandler)
r.AttachHandler(http.MethodGet, DomainBlockPath, m.DomainBlockGETHandler)
r.AttachHandler(http.MethodDelete, DomainBlockPath, m.DomainBlockDELETEHandler)
return nil
}

View file

@ -11,6 +11,7 @@ import (
"github.com/superseriousbusiness/gotosocial/internal/oauth"
)
// DomainBlocksPOSTHandler deals with the creation of a new domain block.
func (m *Module) DomainBlocksPOSTHandler(c *gin.Context) {
l := m.log.WithFields(logrus.Fields{
"func": "DomainBlocksPOSTHandler",
@ -67,5 +68,3 @@ func validateCreateDomainBlock(form *model.DomainBlockCreateRequest) error {
return nil
}

View file

@ -0,0 +1,47 @@
package admin
import (
"net/http"
"github.com/gin-gonic/gin"
"github.com/sirupsen/logrus"
"github.com/superseriousbusiness/gotosocial/internal/oauth"
)
// DomainBlockDELETEHandler deals with the delete of an existing domain block.
func (m *Module) DomainBlockDELETEHandler(c *gin.Context) {
l := m.log.WithFields(logrus.Fields{
"func": "DomainBlockDELETEHandler",
"request_uri": c.Request.RequestURI,
"user_agent": c.Request.UserAgent(),
"origin_ip": c.ClientIP(),
})
// make sure we're authed with an admin account
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
}
if !authed.User.Admin {
l.Debugf("user %s not an admin", authed.User.ID)
c.JSON(http.StatusForbidden, gin.H{"error": "not an admin"})
return
}
domainBlockID := c.Param(IDKey)
if domainBlockID == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "no domain block id provided"})
return
}
domainBlock, errWithCode := m.processor.AdminDomainBlockDelete(authed, domainBlockID)
if errWithCode != nil {
l.Debugf("error deleting domain block: %s", errWithCode.Error())
c.JSON(errWithCode.Code(), gin.H{"error": errWithCode.Safe()})
return
}
c.JSON(http.StatusOK, domainBlock)
}

View file

@ -9,9 +9,10 @@ import (
"github.com/superseriousbusiness/gotosocial/internal/oauth"
)
func (m *Module) DomainBlocksGETHandler(c *gin.Context) {
// DomainBlockGETHandler returns one existing domain block, identified by its id.
func (m *Module) DomainBlockGETHandler(c *gin.Context) {
l := m.log.WithFields(logrus.Fields{
"func": "DomainBlocksPOSTHandler",
"func": "DomainBlockGETHandler",
"request_uri": c.Request.RequestURI,
"user_agent": c.Request.UserAgent(),
"origin_ip": c.ClientIP(),
@ -30,6 +31,12 @@ func (m *Module) DomainBlocksGETHandler(c *gin.Context) {
return
}
domainBlockID := c.Param(IDKey)
if domainBlockID == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "no domain block id provided"})
return
}
export := false
exportString := c.Query(ExportQueryKey)
if exportString != "" {
@ -42,12 +49,12 @@ func (m *Module) DomainBlocksGETHandler(c *gin.Context) {
export = i
}
domainBlocks, err := m.processor.AdminDomainBlocksGet(authed, export)
domainBlock, err := m.processor.AdminDomainBlockGet(authed, domainBlockID, export)
if err != nil {
l.Debugf("error getting domain blocks: %s", err)
l.Debugf("error getting domain block: %s", err)
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, domainBlocks)
c.JSON(http.StatusOK, domainBlock)
}

View file

@ -0,0 +1,54 @@
package admin
import (
"net/http"
"strconv"
"github.com/gin-gonic/gin"
"github.com/sirupsen/logrus"
"github.com/superseriousbusiness/gotosocial/internal/oauth"
)
// DomainBlocksGETHandler returns a list of all existing domain blocks.
func (m *Module) DomainBlocksGETHandler(c *gin.Context) {
l := m.log.WithFields(logrus.Fields{
"func": "DomainBlocksGETHandler",
"request_uri": c.Request.RequestURI,
"user_agent": c.Request.UserAgent(),
"origin_ip": c.ClientIP(),
})
// make sure we're authed with an admin account
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
}
if !authed.User.Admin {
l.Debugf("user %s not an admin", authed.User.ID)
c.JSON(http.StatusForbidden, gin.H{"error": "not an admin"})
return
}
export := false
exportString := c.Query(ExportQueryKey)
if exportString != "" {
i, err := strconv.ParseBool(exportString)
if err != nil {
l.Debugf("error parsing export string: %s", err)
c.JSON(http.StatusBadRequest, gin.H{"error": "couldn't parse export query param"})
return
}
export = i
}
domainBlocks, err := m.processor.AdminDomainBlocksGet(authed, export)
if err != nil {
l.Debugf("error getting domain blocks: %s", err)
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, domainBlocks)
}

View file

@ -8,6 +8,7 @@ import (
"github.com/superseriousbusiness/gotosocial/internal/oauth"
)
// InstanceUpdatePATCHHandler allows an admin to update the instance information served at /api/v1/instance
func (m *Module) InstanceUpdatePATCHHandler(c *gin.Context) {
l := m.log.WithField("func", "InstanceUpdatePATCHHandler")
authed, err := oauth.Authed(c, true, true, true, true)

View file

@ -11,6 +11,9 @@ import (
"github.com/superseriousbusiness/gotosocial/internal/util"
)
// SignatureCheck checks whether an incoming http request has been signed. If so, it will check if the domain
// that signed the request is permitted to access the server. If it is permitted, the handler will set the key
// verifier in the gin context for use down the line.
func (m *Module) SignatureCheck(c *gin.Context) {
l := m.log.WithField("func", "DomainBlockChecker")

View file

@ -235,7 +235,7 @@ func (f *federator) Blocked(ctx context.Context, actorIRIs []*url.URL) (bool, er
}
for _, uri := range actorIRIs {
blockedDomain, err := f.blockedDomain(uri.Host);
blockedDomain, err := f.blockedDomain(uri.Host)
if err != nil {
return false, fmt.Errorf("error checking domain block: %s", err)
}

View file

@ -33,5 +33,13 @@ func (p *processor) AdminDomainBlockCreate(authed *oauth.Auth, form *apimodel.Do
}
func (p *processor) AdminDomainBlocksGet(authed *oauth.Auth, export bool) ([]*apimodel.DomainBlock, gtserror.WithCode) {
return p.adminProcessor.DomainBlocksGet(authed.Account, export)
return p.adminProcessor.DomainBlocksGet(authed.Account, export)
}
func (p *processor) AdminDomainBlockGet(authed *oauth.Auth, id string, export bool) (*apimodel.DomainBlock, gtserror.WithCode) {
return p.adminProcessor.DomainBlockGet(authed.Account, id, export)
}
func (p *processor) AdminDomainBlockDelete(authed *oauth.Auth, id string) (*apimodel.DomainBlock, gtserror.WithCode) {
return p.adminProcessor.DomainBlockDelete(authed.Account, id)
}

View file

@ -33,6 +33,8 @@ import (
type Processor interface {
DomainBlockCreate(account *gtsmodel.Account, form *apimodel.DomainBlockCreateRequest) (*apimodel.DomainBlock, gtserror.WithCode)
DomainBlocksGet(account *gtsmodel.Account, export bool) ([]*apimodel.DomainBlock, gtserror.WithCode)
DomainBlockGet(account *gtsmodel.Account, id string, export bool) (*apimodel.DomainBlock, gtserror.WithCode)
DomainBlockDelete(account *gtsmodel.Account, id string) (*apimodel.DomainBlock, gtserror.WithCode)
EmojiCreate(account *gtsmodel.Account, user *gtsmodel.User, form *apimodel.EmojiCreateRequest) (*apimodel.Emoji, error)
}

View file

@ -0,0 +1,36 @@
package admin
import (
"fmt"
apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
"github.com/superseriousbusiness/gotosocial/internal/db"
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
)
func (p *processor) DomainBlockDelete(account *gtsmodel.Account, id string) (*apimodel.DomainBlock, gtserror.WithCode) {
domainBlock := &gtsmodel.DomainBlock{}
if err := p.db.GetByID(id, domainBlock); err != nil {
if _, ok := err.(db.ErrNoEntries); !ok {
// something has gone really wrong
return nil, gtserror.NewErrorInternalError(err)
}
// there are no entries for this ID
return nil, gtserror.NewErrorNotFound(fmt.Errorf("no entry for ID %s", id))
}
// prepare the domain block to return
mastoDomainBlock, err := p.tc.DomainBlockToMasto(domainBlock, false)
if err != nil {
return nil, gtserror.NewErrorInternalError(err)
}
// delete the domain block
if err := p.db.DeleteByID(id, domainBlock); err != nil {
return nil, gtserror.NewErrorInternalError(err)
}
return mastoDomainBlock, nil
}

View file

@ -0,0 +1,30 @@
package admin
import (
"fmt"
apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
"github.com/superseriousbusiness/gotosocial/internal/db"
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
)
func (p *processor) DomainBlockGet(account *gtsmodel.Account, id string, export bool) (*apimodel.DomainBlock, gtserror.WithCode) {
domainBlock := &gtsmodel.DomainBlock{}
if err := p.db.GetByID(id, domainBlock); err != nil {
if _, ok := err.(db.ErrNoEntries); !ok {
// something has gone really wrong
return nil, gtserror.NewErrorInternalError(err)
}
// there are no entries for this ID
return nil, gtserror.NewErrorNotFound(fmt.Errorf("no entry for ID %s", id))
}
mastoDomainBlock, err := p.tc.DomainBlockToMasto(domainBlock, export)
if err != nil {
return nil, gtserror.NewErrorInternalError(err)
}
return mastoDomainBlock, nil
}

View file

@ -22,10 +22,10 @@ import (
"fmt"
"strings"
apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
"github.com/superseriousbusiness/gotosocial/internal/media"
apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
)
func (p *processor) GetFile(account *gtsmodel.Account, form *apimodel.GetContentRequestForm) (*apimodel.Content, error) {

View file

@ -22,10 +22,10 @@ import (
"errors"
"fmt"
apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
"github.com/superseriousbusiness/gotosocial/internal/db"
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
)
func (p *processor) Update(account *gtsmodel.Account, mediaAttachmentID string, form *apimodel.AttachmentUpdateRequest) (*apimodel.Attachment, gtserror.WithCode) {

View file

@ -89,6 +89,10 @@ type Processor interface {
AdminDomainBlockCreate(authed *oauth.Auth, form *apimodel.DomainBlockCreateRequest) (*apimodel.DomainBlock, gtserror.WithCode)
// AdminDomainBlocksGet returns a list of currently blocked domains.
AdminDomainBlocksGet(authed *oauth.Auth, export bool) ([]*apimodel.DomainBlock, gtserror.WithCode)
// AdminDomainBlockGet returns one domain block, specified by ID.
AdminDomainBlockGet(authed *oauth.Auth, id string, export bool) (*apimodel.DomainBlock, gtserror.WithCode)
// AdminDomainBlockDelete deletes one domain block, specified by ID, returning the deleted domain block.
AdminDomainBlockDelete(authed *oauth.Auth, id string) (*apimodel.DomainBlock, gtserror.WithCode)
// AppCreate processes the creation of a new API application
AppCreate(authed *oauth.Auth, form *apimodel.ApplicationCreateRequest) (*apimodel.Application, error)

View file

@ -648,8 +648,8 @@ func (c *converter) NotificationToMasto(n *gtsmodel.Notification) (*model.Notifi
func (c *converter) DomainBlockToMasto(b *gtsmodel.DomainBlock, export bool) (*model.DomainBlock, error) {
domainBlock := &model.DomainBlock{
Domain: b.Domain,
PublicComment: b.PublicComment,
Domain: b.Domain,
PublicComment: b.PublicComment,
}
// if we're exporting a domain block, return it with minimal information attached

View file

@ -9,7 +9,7 @@ import (
func (f *filter) pullRelevantAccountsFromStatus(targetStatus *gtsmodel.Status) (*relevantAccounts, error) {
accounts := &relevantAccounts{
MentionedAccounts: []*gtsmodel.Account{},
MentionedAccounts: []*gtsmodel.Account{},
BoostedMentionedAccounts: []*gtsmodel.Account{},
}