Implement Cobra CLI tooling, Viper config tooling (#336)

* start pulling out + replacing urfave and config

* replace many many instances of config

* move more stuff => viper

* properly remove urfave

* move some flags to root command

* add testrig commands to root

* alias config file keys

* start adding cli parsing tests

* reorder viper init

* remove config path alias

* fmt

* change config file keys to non-nested

* we're more or less in business now

* tidy up the common func

* go fmt

* get tests passing again

* add note about the cliparsing tests

* reorganize

* update docs with changes

* structure cmd dir better

* rename + move some files around

* fix dangling comma
This commit is contained in:
tobi 2021-12-07 13:31:39 +01:00 committed by GitHub
commit 0884f89431
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
487 changed files with 46667 additions and 8831 deletions

View file

@ -22,7 +22,6 @@ import (
"net/http"
"github.com/superseriousbusiness/gotosocial/internal/api"
"github.com/superseriousbusiness/gotosocial/internal/config"
"github.com/superseriousbusiness/gotosocial/internal/processing"
"github.com/superseriousbusiness/gotosocial/internal/router"
)
@ -38,14 +37,12 @@ const BasePathWithID = BasePath + "/:" + IDKey
// Module implements the ClientAPIModule interface for media
type Module struct {
config *config.Config
processor processing.Processor
}
// New returns a new auth module
func New(config *config.Config, processor processing.Processor) api.ClientModule {
func New(processor processing.Processor) api.ClientModule {
return &Module{
config: config,
processor: processor,
}
}

View file

@ -21,9 +21,11 @@ package media
import (
"errors"
"fmt"
"github.com/sirupsen/logrus"
"net/http"
"github.com/sirupsen/logrus"
"github.com/spf13/viper"
"github.com/gin-gonic/gin"
"github.com/superseriousbusiness/gotosocial/internal/api/model"
"github.com/superseriousbusiness/gotosocial/internal/config"
@ -102,7 +104,7 @@ func (m *Module) MediaCreatePOSTHandler(c *gin.Context) {
// 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 := validateCreateMedia(form, m.config.MediaConfig); err != nil {
if err := validateCreateMedia(form); err != nil {
l.Debugf("error validating form: %s", err)
c.JSON(http.StatusUnprocessableEntity, gin.H{"error": err.Error()})
return
@ -119,24 +121,30 @@ func (m *Module) MediaCreatePOSTHandler(c *gin.Context) {
c.JSON(http.StatusOK, apiAttachment)
}
func validateCreateMedia(form *model.AttachmentRequest, config *config.MediaConfig) error {
func validateCreateMedia(form *model.AttachmentRequest) error {
// check there actually is a file attached and it's not size 0
if form.File == nil {
return errors.New("no attachment given")
}
keys := config.Keys
maxVideoSize := viper.GetInt(keys.MediaVideoMaxSize)
maxImageSize := viper.GetInt(keys.MediaImageMaxSize)
minDescriptionChars := viper.GetInt(keys.MediaDescriptionMinChars)
maxDescriptionChars := viper.GetInt(keys.MediaDescriptionMaxChars)
// a very superficial check to see if no size limits are exceeded
// we still don't actually know which media types we're dealing with but the other handlers will go into more detail there
maxSize := config.MaxVideoSize
if config.MaxImageSize > maxSize {
maxSize = config.MaxImageSize
maxSize := maxVideoSize
if maxImageSize > maxSize {
maxSize = maxImageSize
}
if form.File.Size > int64(maxSize) {
return fmt.Errorf("file size limit exceeded: limit is %d bytes but attachment was %d bytes", maxSize, form.File.Size)
}
if len(form.Description) < config.MinDescriptionChars || len(form.Description) > config.MaxDescriptionChars {
return fmt.Errorf("image description length must be between %d and %d characters (inclusive), but provided image description was %d chars", config.MinDescriptionChars, config.MaxDescriptionChars, len(form.Description))
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))
}
// TODO: validate focus here

View file

@ -35,7 +35,6 @@ import (
"github.com/stretchr/testify/suite"
mediamodule "github.com/superseriousbusiness/gotosocial/internal/api/client/media"
"github.com/superseriousbusiness/gotosocial/internal/api/model"
"github.com/superseriousbusiness/gotosocial/internal/config"
"github.com/superseriousbusiness/gotosocial/internal/db"
"github.com/superseriousbusiness/gotosocial/internal/email"
"github.com/superseriousbusiness/gotosocial/internal/federation"
@ -50,7 +49,6 @@ import (
type MediaCreateTestSuite struct {
// standard suite interfaces
suite.Suite
config *config.Config
db db.DB
storage *kv.KVStore
federator federation.Federator
@ -78,9 +76,9 @@ type MediaCreateTestSuite struct {
func (suite *MediaCreateTestSuite) SetupSuite() {
// setup standard items
suite.config = testrig.NewTestConfig()
suite.db = testrig.NewTestDB()
testrig.InitTestConfig()
testrig.InitTestLog()
suite.db = testrig.NewTestDB()
suite.storage = testrig.NewTestStorage()
suite.tc = testrig.NewTestTypeConverter(suite.db)
suite.mediaHandler = testrig.NewTestMediaHandler(suite.db, suite.storage)
@ -90,7 +88,7 @@ func (suite *MediaCreateTestSuite) SetupSuite() {
suite.processor = testrig.NewTestProcessor(suite.db, suite.storage, suite.federator, suite.emailSender)
// setup module being tested
suite.mediaModule = mediamodule.New(suite.config, suite.processor).(*mediamodule.Module)
suite.mediaModule = mediamodule.New(suite.processor).(*mediamodule.Module)
}
func (suite *MediaCreateTestSuite) TearDownSuite() {

View file

@ -21,9 +21,11 @@ package media
import (
"errors"
"fmt"
"github.com/sirupsen/logrus"
"net/http"
"github.com/sirupsen/logrus"
"github.com/spf13/viper"
"github.com/gin-gonic/gin"
"github.com/superseriousbusiness/gotosocial/internal/api/model"
"github.com/superseriousbusiness/gotosocial/internal/config"
@ -117,7 +119,7 @@ func (m *Module) MediaPUTHandler(c *gin.Context) {
// 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 := validateUpdateMedia(&form, m.config.MediaConfig); err != nil {
if err := validateUpdateMedia(&form); err != nil {
l.Debugf("error validating form: %s", err)
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
@ -132,11 +134,14 @@ func (m *Module) MediaPUTHandler(c *gin.Context) {
c.JSON(http.StatusOK, attachment)
}
func validateUpdateMedia(form *model.AttachmentUpdateRequest, config *config.MediaConfig) error {
func validateUpdateMedia(form *model.AttachmentUpdateRequest) error {
keys := config.Keys
minDescriptionChars := viper.GetInt(keys.MediaDescriptionMinChars)
maxDescriptionChars := viper.GetInt(keys.MediaDescriptionMaxChars)
if form.Description != nil {
if len(*form.Description) < config.MinDescriptionChars || len(*form.Description) > config.MaxDescriptionChars {
return fmt.Errorf("image description length must be between %d and %d characters (inclusive), but provided image description was %d chars", config.MinDescriptionChars, config.MaxDescriptionChars, len(*form.Description))
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))
}
}