Skip to content

Commit

Permalink
Domain block (#76)
Browse files Browse the repository at this point in the history
* start work on admin domain blocking

* move stuff around + further work on domain blocks

* move + restructure processor

* prep work for deleting account

* tidy

* go fmt

* formatting

* domain blocking more work

* check domain blocks way earlier on

* progress on delete account

* delete more stuff when an account is gone

* and more...

* domain blocky block block

* get individual domain block, delete a block
  • Loading branch information
tsmethurst authored Jul 5, 2021
1 parent cf19aaf commit d389e7b
Show file tree
Hide file tree
Showing 100 changed files with 3,432 additions and 1,404 deletions.
2 changes: 1 addition & 1 deletion internal/api/client/account/accountupdate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ func (suite *AccountUpdateTestSuite) SetupTest() {
suite.db = testrig.NewTestDB()
suite.storage = testrig.NewTestStorage()
suite.log = testrig.NewTestLog()
suite.federator = testrig.NewTestFederator(suite.db, testrig.NewTestTransportController(testrig.NewMockHTTPClient(nil)))
suite.federator = testrig.NewTestFederator(suite.db, testrig.NewTestTransportController(testrig.NewMockHTTPClient(nil)), suite.storage)
suite.processor = testrig.NewTestProcessor(suite.db, suite.storage, suite.federator)
suite.accountModule = account.New(suite.config, suite.processor, suite.log).(*account.Module)
testrig.StandardDBSetup(suite.db)
Expand Down
6 changes: 3 additions & 3 deletions internal/api/client/account/statuses.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ func (m *Module) AccountStatusesGETHandler(c *gin.Context) {
maxID = maxIDString
}

pinned := false
pinnedOnly := false
pinnedString := c.Query(PinnedKey)
if pinnedString != "" {
i, err := strconv.ParseBool(pinnedString)
Expand All @@ -91,7 +91,7 @@ func (m *Module) AccountStatusesGETHandler(c *gin.Context) {
c.JSON(http.StatusBadRequest, gin.H{"error": "couldn't parse pinned query param"})
return
}
pinned = i
pinnedOnly = i
}

mediaOnly := false
Expand All @@ -106,7 +106,7 @@ func (m *Module) AccountStatusesGETHandler(c *gin.Context) {
mediaOnly = i
}

statuses, errWithCode := m.processor.AccountStatusesGet(authed, targetAcctID, limit, excludeReplies, maxID, pinned, mediaOnly)
statuses, errWithCode := m.processor.AccountStatusesGet(authed, targetAcctID, limit, excludeReplies, maxID, pinnedOnly, mediaOnly)
if errWithCode != nil {
l.Debugf("error from processor account statuses get: %s", errWithCode)
c.JSON(errWithCode.Code(), gin.H{"error": errWithCode.Safe()})
Expand Down
17 changes: 15 additions & 2 deletions internal/api/client/admin/admin.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,19 @@ import (
)

const (
// BasePath is the base API path for this module
// BasePath is the base API path for this module.
BasePath = "/api/v1/admin"
// EmojiPath is used for posting/deleting custom emojis
// EmojiPath is used for posting/deleting custom emojis.
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 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)
Expand All @@ -54,5 +63,9 @@ func New(config *config.Config, processor processing.Processor, log *logrus.Logg
// Route attaches all routes from this module to the given router
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
}
70 changes: 70 additions & 0 deletions internal/api/client/admin/domainblockcreate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package admin

import (
"errors"
"fmt"
"net/http"

"github.com/gin-gonic/gin"
"github.com/sirupsen/logrus"
"github.com/superseriousbusiness/gotosocial/internal/api/model"
"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",
"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
}

// extract the media create form from the request context
l.Tracef("parsing request form: %+v", c.Request.Form)
form := &model.DomainBlockCreateRequest{}
if err := c.ShouldBind(form); err != nil {
l.Debugf("error parsing form %+v: %s", c.Request.Form, err)
c.JSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintf("could not parse form: %s", err)})
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)
if err := validateCreateDomainBlock(form); err != nil {
l.Debugf("error validating form: %s", err)
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}

domainBlock, err := m.processor.AdminDomainBlockCreate(authed, form)
if err != nil {
l.Debugf("error creating domain block: %s", err)
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}

c.JSON(http.StatusOK, domainBlock)
}

func validateCreateDomainBlock(form *model.DomainBlockCreateRequest) error {
// add some more validation here later if necessary
if form.Domain == "" {
return errors.New("empty domain provided")
}

return nil
}
47 changes: 47 additions & 0 deletions internal/api/client/admin/domainblockdelete.go
Original file line number Diff line number Diff line change
@@ -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)
}
60 changes: 60 additions & 0 deletions internal/api/client/admin/domainblockget.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package admin

import (
"net/http"
"strconv"

"github.com/gin-gonic/gin"
"github.com/sirupsen/logrus"
"github.com/superseriousbusiness/gotosocial/internal/oauth"
)

// DomainBlockGETHandler returns one existing domain block, identified by its id.
func (m *Module) DomainBlockGETHandler(c *gin.Context) {
l := m.log.WithFields(logrus.Fields{
"func": "DomainBlockGETHandler",
"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
}

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
}

domainBlock, err := m.processor.AdminDomainBlockGet(authed, domainBlockID, export)
if err != nil {
l.Debugf("error getting domain block: %s", err)
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}

c.JSON(http.StatusOK, domainBlock)
}
54 changes: 54 additions & 0 deletions internal/api/client/admin/domainblocksget.go
Original file line number Diff line number Diff line change
@@ -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)
}
2 changes: 1 addition & 1 deletion internal/api/client/fileserver/servefile_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ func (suite *ServeFileTestSuite) SetupSuite() {
suite.db = testrig.NewTestDB()
suite.log = testrig.NewTestLog()
suite.storage = testrig.NewTestStorage()
suite.federator = testrig.NewTestFederator(suite.db, testrig.NewTestTransportController(testrig.NewMockHTTPClient(nil)))
suite.federator = testrig.NewTestFederator(suite.db, testrig.NewTestTransportController(testrig.NewMockHTTPClient(nil)), suite.storage)
suite.processor = testrig.NewTestProcessor(suite.db, suite.storage, suite.federator)
suite.tc = testrig.NewTestTypeConverter(suite.db)
suite.mediaHandler = testrig.NewTestMediaHandler(suite.db, suite.storage)
Expand Down
1 change: 1 addition & 0 deletions internal/api/client/instance/instancepatch.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion internal/api/client/media/mediacreate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ func (suite *MediaCreateTestSuite) SetupSuite() {
suite.tc = testrig.NewTestTypeConverter(suite.db)
suite.mediaHandler = testrig.NewTestMediaHandler(suite.db, suite.storage)
suite.oauthServer = testrig.NewTestOauthServer(suite.db)
suite.federator = testrig.NewTestFederator(suite.db, testrig.NewTestTransportController(testrig.NewMockHTTPClient(nil)))
suite.federator = testrig.NewTestFederator(suite.db, testrig.NewTestTransportController(testrig.NewMockHTTPClient(nil)), suite.storage)
suite.processor = testrig.NewTestProcessor(suite.db, suite.storage, suite.federator)

// setup module being tested
Expand Down
2 changes: 1 addition & 1 deletion internal/api/client/status/statusboost_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ func (suite *StatusBoostTestSuite) SetupTest() {
suite.db = testrig.NewTestDB()
suite.storage = testrig.NewTestStorage()
suite.log = testrig.NewTestLog()
suite.federator = testrig.NewTestFederator(suite.db, testrig.NewTestTransportController(testrig.NewMockHTTPClient(nil)))
suite.federator = testrig.NewTestFederator(suite.db, testrig.NewTestTransportController(testrig.NewMockHTTPClient(nil)), suite.storage)
suite.processor = testrig.NewTestProcessor(suite.db, suite.storage, suite.federator)
suite.statusModule = status.New(suite.config, suite.processor, suite.log).(*status.Module)
testrig.StandardDBSetup(suite.db)
Expand Down
2 changes: 1 addition & 1 deletion internal/api/client/status/statuscreate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ func (suite *StatusCreateTestSuite) SetupTest() {
suite.db = testrig.NewTestDB()
suite.storage = testrig.NewTestStorage()
suite.log = testrig.NewTestLog()
suite.federator = testrig.NewTestFederator(suite.db, testrig.NewTestTransportController(testrig.NewMockHTTPClient(nil)))
suite.federator = testrig.NewTestFederator(suite.db, testrig.NewTestTransportController(testrig.NewMockHTTPClient(nil)), suite.storage)
suite.processor = testrig.NewTestProcessor(suite.db, suite.storage, suite.federator)
suite.statusModule = status.New(suite.config, suite.processor, suite.log).(*status.Module)
testrig.StandardDBSetup(suite.db)
Expand Down
2 changes: 1 addition & 1 deletion internal/api/client/status/statusfave_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ func (suite *StatusFaveTestSuite) SetupTest() {
suite.db = testrig.NewTestDB()
suite.storage = testrig.NewTestStorage()
suite.log = testrig.NewTestLog()
suite.federator = testrig.NewTestFederator(suite.db, testrig.NewTestTransportController(testrig.NewMockHTTPClient(nil)))
suite.federator = testrig.NewTestFederator(suite.db, testrig.NewTestTransportController(testrig.NewMockHTTPClient(nil)), suite.storage)
suite.processor = testrig.NewTestProcessor(suite.db, suite.storage, suite.federator)
suite.statusModule = status.New(suite.config, suite.processor, suite.log).(*status.Module)
testrig.StandardDBSetup(suite.db)
Expand Down
2 changes: 1 addition & 1 deletion internal/api/client/status/statusfavedby_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ func (suite *StatusFavedByTestSuite) SetupTest() {
suite.db = testrig.NewTestDB()
suite.storage = testrig.NewTestStorage()
suite.log = testrig.NewTestLog()
suite.federator = testrig.NewTestFederator(suite.db, testrig.NewTestTransportController(testrig.NewMockHTTPClient(nil)))
suite.federator = testrig.NewTestFederator(suite.db, testrig.NewTestTransportController(testrig.NewMockHTTPClient(nil)), suite.storage)
suite.processor = testrig.NewTestProcessor(suite.db, suite.storage, suite.federator)
suite.statusModule = status.New(suite.config, suite.processor, suite.log).(*status.Module)
testrig.StandardDBSetup(suite.db)
Expand Down
2 changes: 1 addition & 1 deletion internal/api/client/status/statusget_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ func (suite *StatusGetTestSuite) SetupTest() {
suite.db = testrig.NewTestDB()
suite.storage = testrig.NewTestStorage()
suite.log = testrig.NewTestLog()
suite.federator = testrig.NewTestFederator(suite.db, testrig.NewTestTransportController(testrig.NewMockHTTPClient(nil)))
suite.federator = testrig.NewTestFederator(suite.db, testrig.NewTestTransportController(testrig.NewMockHTTPClient(nil)), suite.storage)
suite.processor = testrig.NewTestProcessor(suite.db, suite.storage, suite.federator)
suite.statusModule = status.New(suite.config, suite.processor, suite.log).(*status.Module)
testrig.StandardDBSetup(suite.db)
Expand Down
2 changes: 1 addition & 1 deletion internal/api/client/status/statusunfave_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ func (suite *StatusUnfaveTestSuite) SetupTest() {
suite.db = testrig.NewTestDB()
suite.storage = testrig.NewTestStorage()
suite.log = testrig.NewTestLog()
suite.federator = testrig.NewTestFederator(suite.db, testrig.NewTestTransportController(testrig.NewMockHTTPClient(nil)))
suite.federator = testrig.NewTestFederator(suite.db, testrig.NewTestTransportController(testrig.NewMockHTTPClient(nil)), suite.storage)
suite.processor = testrig.NewTestProcessor(suite.db, suite.storage, suite.federator)
suite.statusModule = status.New(suite.config, suite.processor, suite.log).(*status.Module)
testrig.StandardDBSetup(suite.db)
Expand Down
Loading

0 comments on commit d389e7b

Please sign in to comment.