mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2025-12-17 16:53:00 -06:00
start work on admin domain blocking
This commit is contained in:
parent
cf19aaf0df
commit
c7192c0431
4 changed files with 112 additions and 12 deletions
|
|
@ -29,10 +29,12 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// BasePath is the base API path for this module
|
// BasePath is the base API path for this module.
|
||||||
BasePath = "/api/v1/admin"
|
BasePath = "/api/v1/admin"
|
||||||
// EmojiPath is used for posting/deleting custom emojis
|
// EmojiPath is used for posting/deleting custom emojis.
|
||||||
EmojiPath = BasePath + "/custom_emojis"
|
EmojiPath = BasePath + "/custom_emojis"
|
||||||
|
// DomainBlocksPath is used for posting domain blocks.
|
||||||
|
DomainBlocksPath = BasePath + "/domain_blocks"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Module implements the ClientAPIModule interface for admin-related actions (reports, emojis, etc)
|
// Module implements the ClientAPIModule interface for admin-related actions (reports, emojis, etc)
|
||||||
|
|
@ -54,5 +56,6 @@ func New(config *config.Config, processor processing.Processor, log *logrus.Logg
|
||||||
// Route attaches all routes from this module to the given router
|
// Route attaches all routes from this module to the given router
|
||||||
func (m *Module) Route(r router.Router) error {
|
func (m *Module) Route(r router.Router) error {
|
||||||
r.AttachHandler(http.MethodPost, EmojiPath, m.emojiCreatePOSTHandler)
|
r.AttachHandler(http.MethodPost, EmojiPath, m.emojiCreatePOSTHandler)
|
||||||
|
r.AttachHandler(http.MethodPost, DomainBlocksPath, m.DomainBlocksPOSTHandler)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
59
internal/api/client/admin/domainblock.go
Normal file
59
internal/api/client/admin/domainblock.go
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
package admin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"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"
|
||||||
|
)
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
42
internal/api/model/domainblock.go
Normal file
42
internal/api/model/domainblock.go
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package model
|
||||||
|
|
||||||
|
// DomainBlock represents a block on one domain
|
||||||
|
type DomainBlock struct {
|
||||||
|
Domain string `json:"domain"`
|
||||||
|
Obfuscate bool `json:"obfuscate"`
|
||||||
|
PrivateComment string `json:"private_comment"`
|
||||||
|
PublicComment string `json:"public_comment"`
|
||||||
|
SubscriptionID string `json:"subscription_id"`
|
||||||
|
CreatedBy string `json:"created_by"`
|
||||||
|
CreatedAt string `json:"created_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// DomainBlockCreateRequest is the form submitted as a POST to /api/v1/admin/domain_blocks to create a new block.
|
||||||
|
type DomainBlockCreateRequest struct {
|
||||||
|
// hostname/domain to block
|
||||||
|
Domain string `form:"domain" json:"domain" xml:"domain" validation:"required"`
|
||||||
|
// whether the domain should be obfuscated when being displayed publicly
|
||||||
|
Obfuscate bool `form:"obfuscate" json:"obfuscate" xml:"obfuscate"`
|
||||||
|
// private comment for other admins on why the domain was blocked
|
||||||
|
PrivateComment string `form:"private_comment" json:"private_comment" xml:"private_comment"`
|
||||||
|
// public comment on the reason for the domain block
|
||||||
|
PublicComment string `form:"public_comment" json:"public_comment" xml:"public_comment"`
|
||||||
|
}
|
||||||
|
|
@ -20,13 +20,11 @@ package gtsmodel
|
||||||
|
|
||||||
import "time"
|
import "time"
|
||||||
|
|
||||||
// DomainBlock represents a federation block against a particular domain, of varying severity.
|
// DomainBlock represents a federation block against a particular domain
|
||||||
type DomainBlock struct {
|
type DomainBlock struct {
|
||||||
// ID of this block in the database
|
// ID of this block in the database
|
||||||
ID string `pg:"type:CHAR(26),pk,notnull,unique"`
|
ID string `pg:"type:CHAR(26),pk,notnull,unique"`
|
||||||
// Domain to block. If ANY PART of the candidate domain contains this string, it will be blocked.
|
// blocked domain
|
||||||
// For example: 'example.org' also blocks 'gts.example.org'. '.com' blocks *any* '.com' domains.
|
|
||||||
// TODO: implement wildcards here
|
|
||||||
Domain string `pg:",notnull"`
|
Domain string `pg:",notnull"`
|
||||||
// When was this block created
|
// When was this block created
|
||||||
CreatedAt time.Time `pg:"type:timestamp,notnull,default:now()"`
|
CreatedAt time.Time `pg:"type:timestamp,notnull,default:now()"`
|
||||||
|
|
@ -34,14 +32,12 @@ type DomainBlock struct {
|
||||||
UpdatedAt time.Time `pg:"type:timestamp,notnull,default:now()"`
|
UpdatedAt time.Time `pg:"type:timestamp,notnull,default:now()"`
|
||||||
// Account ID of the creator of this block
|
// Account ID of the creator of this block
|
||||||
CreatedByAccountID string `pg:"type:CHAR(26),notnull"`
|
CreatedByAccountID string `pg:"type:CHAR(26),notnull"`
|
||||||
// TODO: define this
|
|
||||||
Severity int
|
|
||||||
// Reject media from this domain?
|
|
||||||
RejectMedia bool
|
|
||||||
// Reject reports from this domain?
|
|
||||||
RejectReports bool
|
|
||||||
// Private comment on this block, viewable to admins
|
// Private comment on this block, viewable to admins
|
||||||
PrivateComment string
|
PrivateComment string
|
||||||
// Public comment on this block, viewable (optionally) by everyone
|
// Public comment on this block, viewable (optionally) by everyone
|
||||||
PublicComment string
|
PublicComment string
|
||||||
|
// whether the domain name should appear obfuscated when displaying it publicly
|
||||||
|
Obfuscate bool
|
||||||
|
// if this block was created through a subscription, what's the subscription ID?
|
||||||
|
SubscriptionID string `pg:"type:CHAR(26)"`
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue