diff options
51 files changed, 310 insertions, 408 deletions
diff --git a/cmd/gotosocial/action/server/server.go b/cmd/gotosocial/action/server/server.go index 57384ac6f..effbc427b 100644 --- a/cmd/gotosocial/action/server/server.go +++ b/cmd/gotosocial/action/server/server.go @@ -98,7 +98,7 @@ var Start action.GTSAction = func(ctx context.Context) error {  	timelineManager := timelineprocessing.NewManager(dbService, typeConverter)  	// Open the storage backend -	storageBasePath := viper.GetString(config.Keys.StorageBasePath) +	storageBasePath := viper.GetString(config.Keys.StorageLocalBasePath)  	storage, err := kv.OpenFile(storageBasePath, nil)  	if err != nil {  		return fmt.Errorf("error creating storage backend: %s", err) diff --git a/cmd/gotosocial/flag/server.go b/cmd/gotosocial/flag/server.go index aa68573a4..434398581 100644 --- a/cmd/gotosocial/flag/server.go +++ b/cmd/gotosocial/flag/server.go @@ -68,10 +68,7 @@ func Media(cmd *cobra.Command, values config.Values) {  // Storage attaches flags pertaining to storage config.  func Storage(cmd *cobra.Command, values config.Values) {  	cmd.Flags().String(config.Keys.StorageBackend, values.StorageBackend, usage.StorageBackend) -	cmd.Flags().String(config.Keys.StorageBasePath, values.StorageBasePath, usage.StorageBasePath) -	cmd.Flags().String(config.Keys.StorageServeProtocol, values.StorageServeProtocol, usage.StorageServeProtocol) -	cmd.Flags().String(config.Keys.StorageServeHost, values.StorageServeHost, usage.StorageServeHost) -	cmd.Flags().String(config.Keys.StorageServeBasePath, values.StorageServeBasePath, usage.StorageServeBasePath) +	cmd.Flags().String(config.Keys.StorageLocalBasePath, values.StorageLocalBasePath, usage.StorageLocalBasePath)  }  // Statuses attaches flags pertaining to statuses config. diff --git a/cmd/gotosocial/flag/usage.go b/cmd/gotosocial/flag/usage.go index ada5ab271..9b5dd31d8 100644 --- a/cmd/gotosocial/flag/usage.go +++ b/cmd/gotosocial/flag/usage.go @@ -48,10 +48,7 @@ var usage = config.KeyNames{  	MediaDescriptionMinChars:   "Min required chars for an image description",  	MediaDescriptionMaxChars:   "Max permitted chars for an image description",  	StorageBackend:             "Storage backend to use for media attachments", -	StorageBasePath:            "Full path to an already-created directory where gts should store/retrieve media files. Subfolders will be created within this dir.", -	StorageServeProtocol:       "Protocol to use for serving media attachments (use https if storage is local)", -	StorageServeHost:           "Hostname to serve media attachments from (use the same value as host if storage is local)", -	StorageServeBasePath:       "Path to append to protocol and hostname to create the base path from which media files will be served (default will mostly be fine)", +	StorageLocalBasePath:       "Full path to an already-created directory where gts should store/retrieve media files. Subfolders will be created within this dir.",  	StatusesMaxChars:           "Max permitted characters for posted statuses",  	StatusesCWMaxChars:         "Max permitted characters for content/spoiler warnings on statuses",  	StatusesPollMaxOptions:     "Max amount of options permitted on a poll", diff --git a/docs/configuration/storage.md b/docs/configuration/storage.md index b0fadcd4c..1fc6d76e7 100644 --- a/docs/configuration/storage.md +++ b/docs/configuration/storage.md @@ -20,25 +20,5 @@ storage-backend: "local"  # this directly, and create new subdirectories and files with in.  # Examples: ["/home/gotosocial/storage", "/opt/gotosocial/datastorage"]  # Default: "/gotosocial/storage" -storage-base-path: "/gotosocial/storage" - -# String. Protocol to use for serving stored files. -# It's very unlikely that you'll need to change this ever, but there might be edge cases. -# Examples: ["http", "https"] -storage-serve-protocol: "https" - -# String. Host for serving stored files. -# If you're using local storage, this should be THE SAME as the value you've set for Host, above. -# It should only be a different value if you're serving stored files from a host -# other than the one your instance is running on. -# Examples: ["localhost", "example.org"] -# Default: "localhost" -- you should absolutely change this. -storage-serve-host: "localhost" - -# String. Base path for serving stored files. This will be added to serveHost and serveProtocol -# to form the prefix url of your stored files. Eg., https://example.org/fileserver/..... -# It's unlikely that you will need to change this. -# Examples: ["/fileserver", "/media"] -# Default: "/fileserver" -storage-serve-base-path: "/fileserver" +storage-local-base-path: "/gotosocial/storage"  ``` diff --git a/docs/installation_guide/binary.md b/docs/installation_guide/binary.md index 576dc52b3..5303359ae 100644 --- a/docs/installation_guide/binary.md +++ b/docs/installation_guide/binary.md @@ -48,11 +48,10 @@ Now open the file in your text editor of choice so that you can set some importa  * Set `host` to whatever hostname you're going to be running the server on (eg., `example.org`).  * Set `port` to `443`. -* Set `db.type` to `sqlite`. -* Set `db.address` to `sqlite.db`. -* Set `storage.basePath` to the storage directory you created above (eg., `/gotosocial/storage`). -* Set `storage.serveHost` to whatever you set the `host` value to above (eg., `example.org`). -* Set `letsEncrypt.certDir` to the certificate storage directory you created above (eg., `/gotosocial/storage/certs`). +* Set `db-type` to `sqlite`. +* Set `db-address` to `sqlite.db`. +* Set `storage-local-base-path` to the storage directory you created above (eg., `/gotosocial/storage`). +* Set `letsencrypt-cert-dir` to the certificate storage directory you created above (eg., `/gotosocial/storage/certs`).  The above options assume you're using SQLite as your database. If you want to use Postgres instead, see [here](../configuration/database.md) for the config options. diff --git a/example/config.yaml b/example/config.yaml index 83f68ef20..af022b241 100644 --- a/example/config.yaml +++ b/example/config.yaml @@ -210,30 +210,10 @@ storage-backend: "local"  # String. Directory to use as a base path for storing files.  # Make sure whatever user/group gotosocial is running as has permission to access -# this directly, and create new subdirectories and files with in. +# this directory, and create new subdirectories and files within it.  # Examples: ["/home/gotosocial/storage", "/opt/gotosocial/datastorage"]  # Default: "/gotosocial/storage" -storage-base-path: "/gotosocial/storage" - -# String. Protocol to use for serving stored files. -# It's very unlikely that you'll need to change this ever, but there might be edge cases. -# Examples: ["http", "https"] -storage-serve-protocol: "https" - -# String. Host for serving stored files. -# If you're using local storage, this should be THE SAME as the value you've set for Host, above. -# It should only be a different value if you're serving stored files from a host -# other than the one your instance is running on. -# Examples: ["localhost", "example.org"] -# Default: "localhost" -- you should absolutely change this. -storage-serve-host: "localhost" - -# String. Base path for serving stored files. This will be added to serveHost and serveProtocol -# to form the prefix url of your stored files. Eg., https://example.org/fileserver/..... -# It's unlikely that you will need to change this. -# Examples: ["/fileserver", "/media"] -# Default: "/fileserver" -storage-serve-base-path: "/fileserver" +storage-local-base-path: "/gotosocial/storage"  ###########################  ##### STATUSES CONFIG ##### diff --git a/internal/ap/contextkey.go b/internal/ap/contextkey.go new file mode 100644 index 000000000..6be65f1db --- /dev/null +++ b/internal/ap/contextkey.go @@ -0,0 +1,41 @@ +/* +   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 ap + +// ContextKey is a type used specifically for settings values on contexts within go-fed AP request chains +type ContextKey string + +const ( +	// ContextActivity can be used to set and retrieve the actual go-fed pub.Activity within a context. +	ContextActivity ContextKey = "activity" +	// ContextReceivingAccount can be used the set and retrieve the account being interacted with / receiving an activity in their inbox. +	ContextReceivingAccount ContextKey = "account" +	// ContextRequestingAccount can be used to set and retrieve the account of an incoming federation request. +	// This will often be the actor of the instance that's posting the request. +	ContextRequestingAccount ContextKey = "requestingAccount" +	// ContextRequestingActorIRI can be used to set and retrieve the actor of an incoming federation request. +	// This will usually be the owner of whatever activity is being posted. +	ContextRequestingActorIRI ContextKey = "requestingActorIRI" +	// ContextRequestingPublicKeyVerifier can be used to set and retrieve the public key verifier of an incoming federation request. +	ContextRequestingPublicKeyVerifier ContextKey = "requestingPublicKeyVerifier" +	// ContextRequestingPublicKeySignature can be used to set and retrieve the value of the signature header of an incoming federation request. +	ContextRequestingPublicKeySignature ContextKey = "requestingPublicKeySignature" +	// ContextFromFederatorChan can be used to pass a pointer to the fromFederator channel into the federator for use in callbacks. +	ContextFromFederatorChan ContextKey = "fromFederatorChan" +) diff --git a/internal/api/client/fileserver/fileserver.go b/internal/api/client/fileserver/fileserver.go index 092a15256..c7b08a8e1 100644 --- a/internal/api/client/fileserver/fileserver.go +++ b/internal/api/client/fileserver/fileserver.go @@ -22,14 +22,15 @@ import (  	"fmt"  	"net/http" -	"github.com/spf13/viper"  	"github.com/superseriousbusiness/gotosocial/internal/api" -	"github.com/superseriousbusiness/gotosocial/internal/config"  	"github.com/superseriousbusiness/gotosocial/internal/processing"  	"github.com/superseriousbusiness/gotosocial/internal/router" +	"github.com/superseriousbusiness/gotosocial/internal/uris"  )  const ( +	// FileServeBasePath forms the first part of the fileserver path. +	FileServeBasePath = "/" + uris.FileserverPath  	// AccountIDKey is the url key for account id (an account ulid)  	AccountIDKey = "account_id"  	// MediaTypeKey is the url key for media type (usually something like attachment or header etc) @@ -43,20 +44,20 @@ const (  // FileServer implements the RESTAPIModule interface.  // The goal here is to serve requested media files if the gotosocial server is configured to use local storage.  type FileServer struct { -	processor            processing.Processor -	storageServeBasePath string +	processor processing.Processor  }  // New returns a new fileServer module  func New(processor processing.Processor) api.ClientModule {  	return &FileServer{ -		processor:            processor, -		storageServeBasePath: viper.GetString(config.Keys.StorageServeBasePath), +		processor: processor,  	}  }  // Route satisfies the RESTAPIModule interface  func (m *FileServer) Route(s router.Router) error { -	s.AttachHandler(http.MethodGet, fmt.Sprintf("%s/:%s/:%s/:%s/:%s", m.storageServeBasePath, AccountIDKey, MediaTypeKey, MediaSizeKey, FileNameKey), m.ServeFile) +	// something like "/fileserver/:account_id/:media_type/:media_size/:file_name" +	fileServePath := fmt.Sprintf("%s/:%s/:%s/:%s/:%s", FileServeBasePath, AccountIDKey, MediaTypeKey, MediaSizeKey, FileNameKey) +	s.AttachHandler(http.MethodGet, fileServePath, m.ServeFile)  	return nil  } diff --git a/internal/api/client/fileserver/servefile_test.go b/internal/api/client/fileserver/servefile_test.go index cf05ebbf1..92646640a 100644 --- a/internal/api/client/fileserver/servefile_test.go +++ b/internal/api/client/fileserver/servefile_test.go @@ -134,11 +134,11 @@ func (suite *ServeFileTestSuite) TestServeOriginalFileSuccessful() {  		},  		gin.Param{  			Key:   fileserver.MediaTypeKey, -			Value: string(media.Attachment), +			Value: string(media.TypeAttachment),  		},  		gin.Param{  			Key:   fileserver.MediaSizeKey, -			Value: string(media.Original), +			Value: string(media.SizeOriginal),  		},  		gin.Param{  			Key:   fileserver.FileNameKey, diff --git a/internal/api/s2s/user/common.go b/internal/api/s2s/user/common.go index c03765bfb..39b78714a 100644 --- a/internal/api/s2s/user/common.go +++ b/internal/api/s2s/user/common.go @@ -22,21 +22,21 @@ import (  	"context"  	"github.com/gin-gonic/gin" -	"github.com/superseriousbusiness/gotosocial/internal/util" +	"github.com/superseriousbusiness/gotosocial/internal/ap"  )  // transferContext transfers the signature verifier and signature from the gin context to the request context  func transferContext(c *gin.Context) context.Context {  	ctx := c.Request.Context() -	verifier, signed := c.Get(string(util.APRequestingPublicKeyVerifier)) +	verifier, signed := c.Get(string(ap.ContextRequestingPublicKeyVerifier))  	if signed { -		ctx = context.WithValue(ctx, util.APRequestingPublicKeyVerifier, verifier) +		ctx = context.WithValue(ctx, ap.ContextRequestingPublicKeyVerifier, verifier)  	} -	signature, signed := c.Get(string(util.APRequestingPublicKeySignature)) +	signature, signed := c.Get(string(ap.ContextRequestingPublicKeySignature))  	if signed { -		ctx = context.WithValue(ctx, util.APRequestingPublicKeySignature, signature) +		ctx = context.WithValue(ctx, ap.ContextRequestingPublicKeySignature, signature)  	}  	return ctx diff --git a/internal/api/s2s/user/user.go b/internal/api/s2s/user/user.go index 891f2c1b1..d1d7d2f58 100644 --- a/internal/api/s2s/user/user.go +++ b/internal/api/s2s/user/user.go @@ -24,7 +24,7 @@ import (  	"github.com/superseriousbusiness/gotosocial/internal/api"  	"github.com/superseriousbusiness/gotosocial/internal/processing"  	"github.com/superseriousbusiness/gotosocial/internal/router" -	"github.com/superseriousbusiness/gotosocial/internal/util" +	"github.com/superseriousbusiness/gotosocial/internal/uris"  )  const ( @@ -42,23 +42,23 @@ const (  	PageKey = "page"  	// UsersBasePath is the base path for serving information about Users eg https://example.org/users -	UsersBasePath = "/" + util.UsersPath +	UsersBasePath = "/" + uris.UsersPath  	// UsersBasePathWithUsername is just the users base path with the Username key in it.  	// Use this anywhere you need to know the username of the user being queried.  	// Eg https://example.org/users/:username  	UsersBasePathWithUsername = UsersBasePath + "/:" + UsernameKey  	// UsersPublicKeyPath is a path to a user's public key, for serving bare minimum AP representations. -	UsersPublicKeyPath = UsersBasePathWithUsername + "/" + util.PublicKeyPath +	UsersPublicKeyPath = UsersBasePathWithUsername + "/" + uris.PublicKeyPath  	// UsersInboxPath is for serving POST requests to a user's inbox with the given username key. -	UsersInboxPath = UsersBasePathWithUsername + "/" + util.InboxPath +	UsersInboxPath = UsersBasePathWithUsername + "/" + uris.InboxPath  	// UsersOutboxPath is for serving GET requests to a user's outbox with the given username key. -	UsersOutboxPath = UsersBasePathWithUsername + "/" + util.OutboxPath +	UsersOutboxPath = UsersBasePathWithUsername + "/" + uris.OutboxPath  	// UsersFollowersPath is for serving GET request's to a user's followers list, with the given username key. -	UsersFollowersPath = UsersBasePathWithUsername + "/" + util.FollowersPath +	UsersFollowersPath = UsersBasePathWithUsername + "/" + uris.FollowersPath  	// UsersFollowingPath is for serving GET request's to a user's following list, with the given username key. -	UsersFollowingPath = UsersBasePathWithUsername + "/" + util.FollowingPath +	UsersFollowingPath = UsersBasePathWithUsername + "/" + uris.FollowingPath  	// UsersStatusPath is for serving GET requests to a particular status by a user, with the given username key and status ID -	UsersStatusPath = UsersBasePathWithUsername + "/" + util.StatusesPath + "/:" + StatusIDKey +	UsersStatusPath = UsersBasePathWithUsername + "/" + uris.StatusesPath + "/:" + StatusIDKey  	// UsersStatusRepliesPath is for serving the replies collection of a status.  	UsersStatusRepliesPath = UsersStatusPath + "/replies"  ) diff --git a/internal/api/s2s/webfinger/webfingerget.go b/internal/api/s2s/webfinger/webfingerget.go index 6b0de69a9..465b6b7d3 100644 --- a/internal/api/s2s/webfinger/webfingerget.go +++ b/internal/api/s2s/webfinger/webfingerget.go @@ -27,9 +27,9 @@ import (  	"github.com/gin-gonic/gin"  	"github.com/sirupsen/logrus"  	"github.com/spf13/viper" +	"github.com/superseriousbusiness/gotosocial/internal/ap"  	"github.com/superseriousbusiness/gotosocial/internal/api"  	"github.com/superseriousbusiness/gotosocial/internal/config" -	"github.com/superseriousbusiness/gotosocial/internal/util"  )  // WebfingerGETRequest swagger:operation GET /.well-known/webfinger webfingerGet @@ -107,9 +107,9 @@ func (m *Module) WebfingerGETRequest(c *gin.Context) {  	// transfer the signature verifier from the gin context to the request context  	ctx := c.Request.Context() -	verifier, signed := c.Get(string(util.APRequestingPublicKeyVerifier)) +	verifier, signed := c.Get(string(ap.ContextRequestingPublicKeyVerifier))  	if signed { -		ctx = context.WithValue(ctx, util.APRequestingPublicKeyVerifier, verifier) +		ctx = context.WithValue(ctx, ap.ContextRequestingPublicKeyVerifier, verifier)  	}  	resp, err := m.processor.GetWebfingerAccount(ctx, username) diff --git a/internal/api/security/signaturecheck.go b/internal/api/security/signaturecheck.go index a0f79e44d..1dd6b5f79 100644 --- a/internal/api/security/signaturecheck.go +++ b/internal/api/security/signaturecheck.go @@ -1,13 +1,14 @@  package security  import ( -	"github.com/sirupsen/logrus"  	"net/http"  	"net/url" +	"github.com/sirupsen/logrus" +	"github.com/superseriousbusiness/gotosocial/internal/ap" +  	"github.com/gin-gonic/gin"  	"github.com/go-fed/httpsig" -	"github.com/superseriousbusiness/gotosocial/internal/util"  )  // SignatureCheck checks whether an incoming http request has been signed. If so, it will check if the domain @@ -42,10 +43,10 @@ func (m *Module) SignatureCheck(c *gin.Context) {  			}  			// set the verifier and signature on the context here to save some work further down the line -			c.Set(string(util.APRequestingPublicKeyVerifier), verifier) +			c.Set(string(ap.ContextRequestingPublicKeyVerifier), verifier)  			signature := c.GetHeader("Signature")  			if signature != "" { -				c.Set(string(util.APRequestingPublicKeySignature), signature) +				c.Set(string(ap.ContextRequestingPublicKeySignature), signature)  			}  		}  	} diff --git a/internal/config/defaults.go b/internal/config/defaults.go index f1666e1a5..4b6ca5ea7 100644 --- a/internal/config/defaults.go +++ b/internal/config/defaults.go @@ -55,10 +55,7 @@ var Defaults = Values{  	MediaDescriptionMaxChars: 500,  	StorageBackend:       "local", -	StorageBasePath:      "/gotosocial/storage", -	StorageServeProtocol: "https", -	StorageServeHost:     "localhost", -	StorageServeBasePath: "/fileserver", +	StorageLocalBasePath: "/gotosocial/storage",  	StatusesMaxChars:           5000,  	StatusesCWMaxChars:         100, diff --git a/internal/config/keys.go b/internal/config/keys.go index a451a8dc6..c3c46745f 100644 --- a/internal/config/keys.go +++ b/internal/config/keys.go @@ -61,10 +61,7 @@ type KeyNames struct {  	// storage  	StorageBackend       string -	StorageBasePath      string -	StorageServeProtocol string -	StorageServeHost     string -	StorageServeBasePath string +	StorageLocalBasePath string  	// statuses  	StatusesMaxChars           string @@ -143,10 +140,7 @@ var Keys = KeyNames{  	MediaDescriptionMaxChars: "media-description-max-chars",  	StorageBackend:       "storage-backend", -	StorageBasePath:      "storage-base-path", -	StorageServeProtocol: "storage-serve-protocol", -	StorageServeHost:     "storage-serve-host", -	StorageServeBasePath: "storage-serve-base-path", +	StorageLocalBasePath: "storage-local-base-path",  	StatusesMaxChars:           "statuses-max-chars",  	StatusesCWMaxChars:         "statuses-cw-max-chars", diff --git a/internal/config/values.go b/internal/config/values.go index a8ffed1af..c1d2946f5 100644 --- a/internal/config/values.go +++ b/internal/config/values.go @@ -53,10 +53,7 @@ type Values struct {  	MediaDescriptionMaxChars int  	StorageBackend       string -	StorageBasePath      string -	StorageServeProtocol string -	StorageServeHost     string -	StorageServeBasePath string +	StorageLocalBasePath string  	StatusesMaxChars           int  	StatusesCWMaxChars         int diff --git a/internal/db/bundb/admin.go b/internal/db/bundb/admin.go index 4b05fdd56..59703ddcc 100644 --- a/internal/db/bundb/admin.go +++ b/internal/db/bundb/admin.go @@ -37,7 +37,7 @@ import (  	"github.com/superseriousbusiness/gotosocial/internal/db"  	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"  	"github.com/superseriousbusiness/gotosocial/internal/id" -	"github.com/superseriousbusiness/gotosocial/internal/util" +	"github.com/superseriousbusiness/gotosocial/internal/uris"  	"golang.org/x/crypto/bcrypt"  ) @@ -100,30 +100,30 @@ func (a *adminDB) NewSignup(ctx context.Context, username string, reason string,  		WhereGroup(" AND ", whereEmptyOrNull("domain")).  		Scan(ctx)  	if err != nil { -		// we just don't have an account yet create one -		newAccountURIs := util.GenerateURIsForAccount(username) -		newAccountID, err := id.NewRandomULID() +		// we just don't have an account yet so create one +		accountURIs := uris.GenerateURIsForAccount(username) +		accountID, err := id.NewRandomULID()  		if err != nil {  			return nil, err  		}  		acct = >smodel.Account{ -			ID:                    newAccountID, +			ID:                    accountID,  			Username:              username,  			DisplayName:           username,  			Reason:                reason,  			Privacy:               gtsmodel.VisibilityDefault, -			URL:                   newAccountURIs.UserURL, +			URL:                   accountURIs.UserURL,  			PrivateKey:            key,  			PublicKey:             &key.PublicKey, -			PublicKeyURI:          newAccountURIs.PublicKeyURI, +			PublicKeyURI:          accountURIs.PublicKeyURI,  			ActorType:             ap.ActorPerson, -			URI:                   newAccountURIs.UserURI, -			InboxURI:              newAccountURIs.InboxURI, -			OutboxURI:             newAccountURIs.OutboxURI, -			FollowersURI:          newAccountURIs.FollowersURI, -			FollowingURI:          newAccountURIs.FollowingURI, -			FeaturedCollectionURI: newAccountURIs.CollectionURI, +			URI:                   accountURIs.UserURI, +			InboxURI:              accountURIs.InboxURI, +			OutboxURI:             accountURIs.OutboxURI, +			FollowersURI:          accountURIs.FollowersURI, +			FollowingURI:          accountURIs.FollowingURI, +			FeaturedCollectionURI: accountURIs.CollectionURI,  		}  		if _, err = a.conn.  			NewInsert(). @@ -204,7 +204,7 @@ func (a *adminDB) CreateInstanceAccount(ctx context.Context) db.Error {  		return err  	} -	newAccountURIs := util.GenerateURIsForAccount(username) +	newAccountURIs := uris.GenerateURIsForAccount(username)  	acct := >smodel.Account{  		ID:                    aID,  		Username:              username, diff --git a/internal/federation/authenticate.go b/internal/federation/authenticate.go index 9d715c549..44e527dcb 100644 --- a/internal/federation/authenticate.go +++ b/internal/federation/authenticate.go @@ -35,10 +35,10 @@ import (  	"github.com/superseriousbusiness/activity/pub"  	"github.com/superseriousbusiness/activity/streams"  	"github.com/superseriousbusiness/activity/streams/vocab" +	"github.com/superseriousbusiness/gotosocial/internal/ap"  	"github.com/superseriousbusiness/gotosocial/internal/config"  	"github.com/superseriousbusiness/gotosocial/internal/db"  	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" -	"github.com/superseriousbusiness/gotosocial/internal/util"  )  /* @@ -123,7 +123,7 @@ func (f *federator) AuthenticateFederatedRequest(ctx context.Context, requestedU  	var err error  	// thanks to signaturecheck.go in the security package, we should already have a signature verifier set on the context -	vi := ctx.Value(util.APRequestingPublicKeyVerifier) +	vi := ctx.Value(ap.ContextRequestingPublicKeyVerifier)  	if vi == nil {  		l.Debug("request wasn't signed")  		return nil, false, nil // request wasn't signed @@ -136,7 +136,7 @@ func (f *federator) AuthenticateFederatedRequest(ctx context.Context, requestedU  	}  	// we should have the signature itself set too -	si := ctx.Value(util.APRequestingPublicKeySignature) +	si := ctx.Value(ap.ContextRequestingPublicKeySignature)  	if vi == nil {  		l.Debug("request wasn't signed")  		return nil, false, nil // request wasn't signed diff --git a/internal/federation/dereferencing/thread.go b/internal/federation/dereferencing/thread.go index 209df32c4..4ff061d93 100644 --- a/internal/federation/dereferencing/thread.go +++ b/internal/federation/dereferencing/thread.go @@ -27,7 +27,7 @@ import (  	"github.com/spf13/viper"  	"github.com/superseriousbusiness/gotosocial/internal/ap"  	"github.com/superseriousbusiness/gotosocial/internal/config" -	"github.com/superseriousbusiness/gotosocial/internal/util" +	"github.com/superseriousbusiness/gotosocial/internal/uris"  )  // DereferenceThread takes a statusable (something that has withReplies and withInReplyTo), @@ -85,7 +85,7 @@ func (d *deref) iterateAncestors(ctx context.Context, username string, statusIRI  		l.Debug("iri belongs to us, moving up to next ancestor")  		// since this is our status, we know we can extract the id from the status path -		_, id, err := util.ParseStatusesPath(&statusIRI) +		_, id, err := uris.ParseStatusesPath(&statusIRI)  		if err != nil {  			return err  		} diff --git a/internal/federation/federatingdb/accept.go b/internal/federation/federatingdb/accept.go index 8efb29b53..34cdc4fb5 100644 --- a/internal/federation/federatingdb/accept.go +++ b/internal/federation/federatingdb/accept.go @@ -29,7 +29,7 @@ import (  	"github.com/superseriousbusiness/gotosocial/internal/db"  	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"  	"github.com/superseriousbusiness/gotosocial/internal/messages" -	"github.com/superseriousbusiness/gotosocial/internal/util" +	"github.com/superseriousbusiness/gotosocial/internal/uris"  )  func (f *federatingDB) Accept(ctx context.Context, accept vocab.ActivityStreamsAccept) error { @@ -66,7 +66,7 @@ func (f *federatingDB) Accept(ctx context.Context, accept vocab.ActivityStreamsA  		if iter.IsIRI() {  			// we have just the URI of whatever is being accepted, so we need to find out what it is  			acceptedObjectIRI := iter.GetIRI() -			if util.IsFollowPath(acceptedObjectIRI) { +			if uris.IsFollowPath(acceptedObjectIRI) {  				// ACCEPT FOLLOW  				gtsFollowRequest := >smodel.FollowRequest{}  				if err := f.db.GetWhere(ctx, []db.Where{{Key: "uri", Value: acceptedObjectIRI.String()}}, gtsFollowRequest); err != nil { diff --git a/internal/federation/federatingdb/federatingdb_test.go b/internal/federation/federatingdb/federatingdb_test.go index d51e0a825..71cc739c4 100644 --- a/internal/federation/federatingdb/federatingdb_test.go +++ b/internal/federation/federatingdb/federatingdb_test.go @@ -22,12 +22,12 @@ import (  	"context"  	"github.com/stretchr/testify/suite" +	"github.com/superseriousbusiness/gotosocial/internal/ap"  	"github.com/superseriousbusiness/gotosocial/internal/db"  	"github.com/superseriousbusiness/gotosocial/internal/federation/federatingdb"  	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"  	"github.com/superseriousbusiness/gotosocial/internal/messages"  	"github.com/superseriousbusiness/gotosocial/internal/typeutils" -	"github.com/superseriousbusiness/gotosocial/internal/util"  	"github.com/superseriousbusiness/gotosocial/testrig"  ) @@ -75,8 +75,8 @@ func (suite *FederatingDBTestSuite) TearDownTest() {  func createTestContext(receivingAccount *gtsmodel.Account, requestingAccount *gtsmodel.Account, fromFederatorChan chan messages.FromFederator) context.Context {  	ctx := context.Background() -	ctx = context.WithValue(ctx, util.APReceivingAccount, receivingAccount) -	ctx = context.WithValue(ctx, util.APRequestingAccount, requestingAccount) -	ctx = context.WithValue(ctx, util.APFromFederatorChanKey, fromFederatorChan) +	ctx = context.WithValue(ctx, ap.ContextReceivingAccount, receivingAccount) +	ctx = context.WithValue(ctx, ap.ContextRequestingAccount, requestingAccount) +	ctx = context.WithValue(ctx, ap.ContextFromFederatorChan, fromFederatorChan)  	return ctx  } diff --git a/internal/federation/federatingdb/get.go b/internal/federation/federatingdb/get.go index a409b7b91..ac3920c78 100644 --- a/internal/federation/federatingdb/get.go +++ b/internal/federation/federatingdb/get.go @@ -25,7 +25,7 @@ import (  	"github.com/sirupsen/logrus"  	"github.com/superseriousbusiness/activity/streams/vocab" -	"github.com/superseriousbusiness/gotosocial/internal/util" +	"github.com/superseriousbusiness/gotosocial/internal/uris"  )  // Get returns the database entry for the specified id. @@ -40,7 +40,7 @@ func (f *federatingDB) Get(ctx context.Context, id *url.URL) (value vocab.Type,  	)  	l.Debug("entering Get") -	if util.IsUserPath(id) { +	if uris.IsUserPath(id) {  		acct, err := f.db.GetAccountByURI(ctx, id.String())  		if err != nil {  			return nil, err @@ -48,7 +48,7 @@ func (f *federatingDB) Get(ctx context.Context, id *url.URL) (value vocab.Type,  		return f.typeConverter.AccountToAS(ctx, acct)  	} -	if util.IsStatusesPath(id) { +	if uris.IsStatusesPath(id) {  		status, err := f.db.GetStatusByURI(ctx, id.String())  		if err != nil {  			return nil, err @@ -56,11 +56,11 @@ func (f *federatingDB) Get(ctx context.Context, id *url.URL) (value vocab.Type,  		return f.typeConverter.StatusToAS(ctx, status)  	} -	if util.IsFollowersPath(id) { +	if uris.IsFollowersPath(id) {  		return f.Followers(ctx, id)  	} -	if util.IsFollowingPath(id) { +	if uris.IsFollowingPath(id) {  		return f.Following(ctx, id)  	} diff --git a/internal/federation/federatingdb/owns.go b/internal/federation/federatingdb/owns.go index 2603c9aa2..15e3dea0a 100644 --- a/internal/federation/federatingdb/owns.go +++ b/internal/federation/federatingdb/owns.go @@ -28,7 +28,7 @@ import (  	"github.com/superseriousbusiness/gotosocial/internal/config"  	"github.com/superseriousbusiness/gotosocial/internal/db"  	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" -	"github.com/superseriousbusiness/gotosocial/internal/util" +	"github.com/superseriousbusiness/gotosocial/internal/uris"  )  // Owns returns true if the IRI belongs to this instance, and if @@ -52,8 +52,8 @@ func (f *federatingDB) Owns(ctx context.Context, id *url.URL) (bool, error) {  	// apparently it belongs to this host, so what *is* it?  	// check if it's a status, eg /users/example_username/statuses/SOME_UUID_OF_A_STATUS -	if util.IsStatusesPath(id) { -		_, uid, err := util.ParseStatusesPath(id) +	if uris.IsStatusesPath(id) { +		_, uid, err := uris.ParseStatusesPath(id)  		if err != nil {  			return false, fmt.Errorf("error parsing statuses path for url %s: %s", id.String(), err)  		} @@ -69,8 +69,8 @@ func (f *federatingDB) Owns(ctx context.Context, id *url.URL) (bool, error) {  		return status.Local, nil  	} -	if util.IsUserPath(id) { -		username, err := util.ParseUserPath(id) +	if uris.IsUserPath(id) { +		username, err := uris.ParseUserPath(id)  		if err != nil {  			return false, fmt.Errorf("error parsing statuses path for url %s: %s", id.String(), err)  		} @@ -86,8 +86,8 @@ func (f *federatingDB) Owns(ctx context.Context, id *url.URL) (bool, error) {  		return true, nil  	} -	if util.IsFollowersPath(id) { -		username, err := util.ParseFollowersPath(id) +	if uris.IsFollowersPath(id) { +		username, err := uris.ParseFollowersPath(id)  		if err != nil {  			return false, fmt.Errorf("error parsing statuses path for url %s: %s", id.String(), err)  		} @@ -103,8 +103,8 @@ func (f *federatingDB) Owns(ctx context.Context, id *url.URL) (bool, error) {  		return true, nil  	} -	if util.IsFollowingPath(id) { -		username, err := util.ParseFollowingPath(id) +	if uris.IsFollowingPath(id) { +		username, err := uris.ParseFollowingPath(id)  		if err != nil {  			return false, fmt.Errorf("error parsing statuses path for url %s: %s", id.String(), err)  		} @@ -120,8 +120,8 @@ func (f *federatingDB) Owns(ctx context.Context, id *url.URL) (bool, error) {  		return true, nil  	} -	if util.IsLikePath(id) { -		username, likeID, err := util.ParseLikedPath(id) +	if uris.IsLikePath(id) { +		username, likeID, err := uris.ParseLikedPath(id)  		if err != nil {  			return false, fmt.Errorf("error parsing like path for url %s: %s", id.String(), err)  		} @@ -145,8 +145,8 @@ func (f *federatingDB) Owns(ctx context.Context, id *url.URL) (bool, error) {  		return true, nil  	} -	if util.IsBlockPath(id) { -		username, blockID, err := util.ParseBlockPath(id) +	if uris.IsBlockPath(id) { +		username, blockID, err := uris.ParseBlockPath(id)  		if err != nil {  			return false, fmt.Errorf("error parsing block path for url %s: %s", id.String(), err)  		} diff --git a/internal/federation/federatingdb/reject.go b/internal/federation/federatingdb/reject.go index 15d4a87ae..2ecdc829e 100644 --- a/internal/federation/federatingdb/reject.go +++ b/internal/federation/federatingdb/reject.go @@ -28,7 +28,7 @@ import (  	"github.com/superseriousbusiness/gotosocial/internal/ap"  	"github.com/superseriousbusiness/gotosocial/internal/db"  	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" -	"github.com/superseriousbusiness/gotosocial/internal/util" +	"github.com/superseriousbusiness/gotosocial/internal/uris"  )  func (f *federatingDB) Reject(ctx context.Context, reject vocab.ActivityStreamsReject) error { @@ -65,7 +65,7 @@ func (f *federatingDB) Reject(ctx context.Context, reject vocab.ActivityStreamsR  		if iter.IsIRI() {  			// we have just the URI of whatever is being rejected, so we need to find out what it is  			rejectedObjectIRI := iter.GetIRI() -			if util.IsFollowPath(rejectedObjectIRI) { +			if uris.IsFollowPath(rejectedObjectIRI) {  				// REJECT FOLLOW  				gtsFollowRequest := >smodel.FollowRequest{}  				if err := f.db.GetWhere(ctx, []db.Where{{Key: "uri", Value: rejectedObjectIRI.String()}}, gtsFollowRequest); err != nil { diff --git a/internal/federation/federatingdb/reject_test.go b/internal/federation/federatingdb/reject_test.go index 9930d83d2..700330c1f 100644 --- a/internal/federation/federatingdb/reject_test.go +++ b/internal/federation/federatingdb/reject_test.go @@ -27,7 +27,7 @@ import (  	"github.com/superseriousbusiness/gotosocial/internal/db"  	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"  	"github.com/superseriousbusiness/gotosocial/internal/messages" -	"github.com/superseriousbusiness/gotosocial/internal/util" +	"github.com/superseriousbusiness/gotosocial/internal/uris"  	"github.com/superseriousbusiness/gotosocial/testrig"  ) @@ -48,7 +48,7 @@ func (suite *RejectTestSuite) TestRejectFollowRequest() {  		ID:              "01FJ1S8DX3STJJ6CEYPMZ1M0R3",  		CreatedAt:       time.Now(),  		UpdatedAt:       time.Now(), -		URI:             util.GenerateURIForFollow(followingAccount.Username, "01FJ1S8DX3STJJ6CEYPMZ1M0R3"), +		URI:             uris.GenerateURIForFollow(followingAccount.Username, "01FJ1S8DX3STJJ6CEYPMZ1M0R3"),  		AccountID:       followingAccount.ID,  		TargetAccountID: followedAccount.ID,  	} diff --git a/internal/federation/federatingdb/update.go b/internal/federation/federatingdb/update.go index 1d56b931f..e95e128cd 100644 --- a/internal/federation/federatingdb/update.go +++ b/internal/federation/federatingdb/update.go @@ -30,7 +30,6 @@ import (  	"github.com/superseriousbusiness/gotosocial/internal/config"  	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"  	"github.com/superseriousbusiness/gotosocial/internal/messages" -	"github.com/superseriousbusiness/gotosocial/internal/util"  )  // Update sets an existing entry to the database based on the value's @@ -66,7 +65,7 @@ func (f *federatingDB) Update(ctx context.Context, asType vocab.Type) error {  		return nil  	} -	requestingAcctI := ctx.Value(util.APRequestingAccount) +	requestingAcctI := ctx.Value(ap.ContextRequestingAccount)  	if requestingAcctI == nil {  		l.Error("UPDATE: requesting account wasn't set on context")  	} diff --git a/internal/federation/federatingdb/util.go b/internal/federation/federatingdb/util.go index afa09e39d..56512e0af 100644 --- a/internal/federation/federatingdb/util.go +++ b/internal/federation/federatingdb/util.go @@ -35,7 +35,7 @@ import (  	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"  	"github.com/superseriousbusiness/gotosocial/internal/id"  	"github.com/superseriousbusiness/gotosocial/internal/messages" -	"github.com/superseriousbusiness/gotosocial/internal/util" +	"github.com/superseriousbusiness/gotosocial/internal/uris"  )  func sameActor(activityActor vocab.ActivityStreamsActorProperty, followActor vocab.ActivityStreamsActorProperty) bool { @@ -106,7 +106,7 @@ func (f *federatingDB) NewID(ctx context.Context, t vocab.Type) (idURL *url.URL,  						if err != nil {  							return nil, err  						} -						return url.Parse(util.GenerateURIForFollow(actorAccount.Username, newID)) +						return url.Parse(uris.GenerateURIForFollow(actorAccount.Username, newID))  					}  				}  			} @@ -241,7 +241,7 @@ func (f *federatingDB) ActorForInbox(ctx context.Context, inboxIRI *url.URL) (ac  func (f *federatingDB) getAccountForIRI(ctx context.Context, iri *url.URL) (account *gtsmodel.Account, err error) {  	acct := >smodel.Account{} -	if util.IsInboxPath(iri) { +	if uris.IsInboxPath(iri) {  		if err := f.db.GetWhere(ctx, []db.Where{{Key: "inbox_uri", Value: iri.String()}}, acct); err != nil {  			if err == db.ErrNoEntries {  				return nil, fmt.Errorf("no actor found that corresponds to inbox %s", iri.String()) @@ -251,7 +251,7 @@ func (f *federatingDB) getAccountForIRI(ctx context.Context, iri *url.URL) (acco  		return acct, nil  	} -	if util.IsOutboxPath(iri) { +	if uris.IsOutboxPath(iri) {  		if err := f.db.GetWhere(ctx, []db.Where{{Key: "outbox_uri", Value: iri.String()}}, acct); err != nil {  			if err == db.ErrNoEntries {  				return nil, fmt.Errorf("no actor found that corresponds to outbox %s", iri.String()) @@ -261,7 +261,7 @@ func (f *federatingDB) getAccountForIRI(ctx context.Context, iri *url.URL) (acco  		return acct, nil  	} -	if util.IsUserPath(iri) { +	if uris.IsUserPath(iri) {  		if err := f.db.GetWhere(ctx, []db.Where{{Key: "uri", Value: iri.String()}}, acct); err != nil {  			if err == db.ErrNoEntries {  				return nil, fmt.Errorf("no actor found that corresponds to uri %s", iri.String()) @@ -271,7 +271,7 @@ func (f *federatingDB) getAccountForIRI(ctx context.Context, iri *url.URL) (acco  		return acct, nil  	} -	if util.IsFollowersPath(iri) { +	if uris.IsFollowersPath(iri) {  		if err := f.db.GetWhere(ctx, []db.Where{{Key: "followers_uri", Value: iri.String()}}, acct); err != nil {  			if err == db.ErrNoEntries {  				return nil, fmt.Errorf("no actor found that corresponds to followers_uri %s", iri.String()) @@ -281,7 +281,7 @@ func (f *federatingDB) getAccountForIRI(ctx context.Context, iri *url.URL) (acco  		return acct, nil  	} -	if util.IsFollowingPath(iri) { +	if uris.IsFollowingPath(iri) {  		if err := f.db.GetWhere(ctx, []db.Where{{Key: "following_uri", Value: iri.String()}}, acct); err != nil {  			if err == db.ErrNoEntries {  				return nil, fmt.Errorf("no actor found that corresponds to following_uri %s", iri.String()) @@ -311,30 +311,30 @@ func (f *federatingDB) collectIRIs(ctx context.Context, iris []*url.URL) (vocab.  //   - A channel that messages for the processor can be placed into.  // If a value is not present, nil will be returned for it. It's up to the caller to check this and respond appropriately.  func extractFromCtx(ctx context.Context) (receivingAccount, requestingAccount *gtsmodel.Account, fromFederatorChan chan messages.FromFederator) { -	receivingAccountI := ctx.Value(util.APReceivingAccount) +	receivingAccountI := ctx.Value(ap.ContextReceivingAccount)  	if receivingAccountI != nil {  		var ok bool  		receivingAccount, ok = receivingAccountI.(*gtsmodel.Account)  		if !ok { -			logrus.Panicf("extractFromCtx: context entry with key %s could not be asserted to *gtsmodel.Account", util.APReceivingAccount) +			logrus.Panicf("extractFromCtx: context entry with key %s could not be asserted to *gtsmodel.Account", ap.ContextReceivingAccount)  		}  	} -	requestingAcctI := ctx.Value(util.APRequestingAccount) +	requestingAcctI := ctx.Value(ap.ContextRequestingAccount)  	if requestingAcctI != nil {  		var ok bool  		requestingAccount, ok = requestingAcctI.(*gtsmodel.Account)  		if !ok { -			logrus.Panicf("extractFromCtx: context entry with key %s could not be asserted to *gtsmodel.Account", util.APRequestingAccount) +			logrus.Panicf("extractFromCtx: context entry with key %s could not be asserted to *gtsmodel.Account", ap.ContextRequestingAccount)  		}  	} -	fromFederatorChanI := ctx.Value(util.APFromFederatorChanKey) +	fromFederatorChanI := ctx.Value(ap.ContextFromFederatorChan)  	if fromFederatorChanI != nil {  		var ok bool  		fromFederatorChan, ok = fromFederatorChanI.(chan messages.FromFederator)  		if !ok { -			logrus.Panicf("extractFromCtx: context entry with key %s could not be asserted to chan messages.FromFederator", util.APFromFederatorChanKey) +			logrus.Panicf("extractFromCtx: context entry with key %s could not be asserted to chan messages.FromFederator", ap.ContextFromFederatorChan)  		}  	} diff --git a/internal/federation/federatingprotocol.go b/internal/federation/federatingprotocol.go index be5ab4d85..636fed3c5 100644 --- a/internal/federation/federatingprotocol.go +++ b/internal/federation/federatingprotocol.go @@ -29,9 +29,10 @@ import (  	"github.com/superseriousbusiness/activity/pub"  	"github.com/superseriousbusiness/activity/streams"  	"github.com/superseriousbusiness/activity/streams/vocab" +	"github.com/superseriousbusiness/gotosocial/internal/ap"  	"github.com/superseriousbusiness/gotosocial/internal/db"  	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" -	"github.com/superseriousbusiness/gotosocial/internal/util" +	"github.com/superseriousbusiness/gotosocial/internal/uris"  )  /* @@ -73,7 +74,7 @@ func (f *federator) PostInboxRequestBodyHook(ctx context.Context, r *http.Reques  		return nil, err  	}  	// set the activity on the context for use later on -	return context.WithValue(ctx, util.APActivity, activity), nil +	return context.WithValue(ctx, ap.ContextActivity, activity), nil  }  // AuthenticatePostInbox delegates the authentication of a POST to an @@ -100,11 +101,11 @@ func (f *federator) AuthenticatePostInbox(ctx context.Context, w http.ResponseWr  	})  	l.Trace("received request to authenticate") -	if !util.IsInboxPath(r.URL) { +	if !uris.IsInboxPath(r.URL) {  		return nil, false, fmt.Errorf("path %s was not an inbox path", r.URL.String())  	} -	username, err := util.ParseInboxPath(r.URL) +	username, err := uris.ParseInboxPath(r.URL)  	if err != nil {  		return nil, false, fmt.Errorf("could not parse path %s: %s", r.URL.String(), err)  	} @@ -157,8 +158,8 @@ func (f *federator) AuthenticatePostInbox(ctx context.Context, w http.ResponseWr  		return nil, false, fmt.Errorf("couldn't get requesting account %s: %s", publicKeyOwnerURI, err)  	} -	withRequesting := context.WithValue(ctx, util.APRequestingAccount, requestingAccount) -	withReceiving := context.WithValue(withRequesting, util.APReceivingAccount, receivingAccount) +	withRequesting := context.WithValue(ctx, ap.ContextRequestingAccount, requestingAccount) +	withReceiving := context.WithValue(withRequesting, ap.ContextReceivingAccount, receivingAccount)  	return withReceiving, true, nil  } @@ -182,7 +183,7 @@ func (f *federator) Blocked(ctx context.Context, actorIRIs []*url.URL) (bool, er  	})  	l.Debugf("entering BLOCKED function with IRI list: %+v", actorIRIs) -	receivingAccountI := ctx.Value(util.APReceivingAccount) +	receivingAccountI := ctx.Value(ap.ContextReceivingAccount)  	receivingAccount, ok := receivingAccountI.(*gtsmodel.Account)  	if !ok {  		l.Errorf("receiving account not set on request context") diff --git a/internal/federation/federator_test.go b/internal/federation/federator_test.go index f907ac00b..20a0b7d46 100644 --- a/internal/federation/federator_test.go +++ b/internal/federation/federator_test.go @@ -30,11 +30,11 @@ import (  	"github.com/stretchr/testify/suite"  	"github.com/superseriousbusiness/activity/pub" +	"github.com/superseriousbusiness/gotosocial/internal/ap"  	"github.com/superseriousbusiness/gotosocial/internal/db"  	"github.com/superseriousbusiness/gotosocial/internal/federation"  	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"  	"github.com/superseriousbusiness/gotosocial/internal/typeutils" -	"github.com/superseriousbusiness/gotosocial/internal/util"  	"github.com/superseriousbusiness/gotosocial/testrig"  ) @@ -91,7 +91,7 @@ func (suite *ProtocolTestSuite) TestPostInboxRequestBodyHook() {  	assert.NotNil(suite.T(), newContext)  	// activity should be set on context now -	activityI := newContext.Value(util.APActivity) +	activityI := newContext.Value(ap.ContextActivity)  	assert.NotNil(suite.T(), activityI)  	returnedActivity, ok := activityI.(pub.Activity)  	assert.True(suite.T(), ok) @@ -121,10 +121,10 @@ func (suite *ProtocolTestSuite) TestAuthenticatePostInbox() {  	ctx := context.Background()  	// by the time AuthenticatePostInbox is called, PostInboxRequestBodyHook should have already been called,  	// which should have set the account and username onto the request. We can replicate that behavior here: -	ctxWithAccount := context.WithValue(ctx, util.APReceivingAccount, inboxAccount) -	ctxWithActivity := context.WithValue(ctxWithAccount, util.APActivity, activity) -	ctxWithVerifier := context.WithValue(ctxWithActivity, util.APRequestingPublicKeyVerifier, verifier) -	ctxWithSignature := context.WithValue(ctxWithVerifier, util.APRequestingPublicKeySignature, activity.SignatureHeader) +	ctxWithAccount := context.WithValue(ctx, ap.ContextReceivingAccount, inboxAccount) +	ctxWithActivity := context.WithValue(ctxWithAccount, ap.ContextActivity, activity) +	ctxWithVerifier := context.WithValue(ctxWithActivity, ap.ContextRequestingPublicKeyVerifier, verifier) +	ctxWithSignature := context.WithValue(ctxWithVerifier, ap.ContextRequestingPublicKeySignature, activity.SignatureHeader)  	// we can pass this recorder as a writer and read it back after  	recorder := httptest.NewRecorder() @@ -135,7 +135,7 @@ func (suite *ProtocolTestSuite) TestAuthenticatePostInbox() {  	assert.True(suite.T(), authed)  	// since we know this account already it should be set on the context -	requestingAccountI := newContext.Value(util.APRequestingAccount) +	requestingAccountI := newContext.Value(ap.ContextRequestingAccount)  	assert.NotNil(suite.T(), requestingAccountI)  	requestingAccount, ok := requestingAccountI.(*gtsmodel.Account)  	assert.True(suite.T(), ok) diff --git a/internal/federation/transport.go b/internal/federation/transport.go index 3287f6952..1391b90d7 100644 --- a/internal/federation/transport.go +++ b/internal/federation/transport.go @@ -24,7 +24,7 @@ import (  	"net/url"  	"github.com/superseriousbusiness/activity/pub" -	"github.com/superseriousbusiness/gotosocial/internal/util" +	"github.com/superseriousbusiness/gotosocial/internal/uris"  )  // NewTransport returns a new Transport on behalf of a specific actor. @@ -55,13 +55,13 @@ func (f *federator) NewTransport(ctx context.Context, actorBoxIRI *url.URL, gofe  	var err error  	switch { -	case util.IsInboxPath(actorBoxIRI): -		username, err = util.ParseInboxPath(actorBoxIRI) +	case uris.IsInboxPath(actorBoxIRI): +		username, err = uris.ParseInboxPath(actorBoxIRI)  		if err != nil {  			return nil, fmt.Errorf("couldn't parse path %s as an inbox: %s", actorBoxIRI.String(), err)  		} -	case util.IsOutboxPath(actorBoxIRI): -		username, err = util.ParseOutboxPath(actorBoxIRI) +	case uris.IsOutboxPath(actorBoxIRI): +		username, err = uris.ParseOutboxPath(actorBoxIRI)  		if err != nil {  			return nil, fmt.Errorf("couldn't parse path %s as an outbox: %s", actorBoxIRI.String(), err)  		} diff --git a/internal/media/handler.go b/internal/media/handler.go index 24963e404..98c65ff36 100644 --- a/internal/media/handler.go +++ b/internal/media/handler.go @@ -28,39 +28,31 @@ import (  	"codeberg.org/gruf/go-store/kv"  	"github.com/sirupsen/logrus" -	"github.com/spf13/viper" -	"github.com/superseriousbusiness/gotosocial/internal/config"  	"github.com/superseriousbusiness/gotosocial/internal/db"  	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"  	"github.com/superseriousbusiness/gotosocial/internal/id"  	"github.com/superseriousbusiness/gotosocial/internal/transport" +	"github.com/superseriousbusiness/gotosocial/internal/uris"  ) -// Size describes the *size* of a piece of media +// EmojiMaxBytes is the maximum permitted bytes of an emoji upload (50kb) +const EmojiMaxBytes = 51200 +  type Size string -// Type describes the *type* of a piece of media +const ( +	SizeSmall    Size = "small"    // SizeSmall is the key for small/thumbnail versions of media +	SizeOriginal Size = "original" // SizeOriginal is the key for original/fullsize versions of media and emoji +	SizeStatic   Size = "static"   // SizeStatic is the key for static (non-animated) versions of emoji +) +  type Type string  const ( -	// Small is the key for small/thumbnail versions of media -	Small Size = "small" -	// Original is the key for original/fullsize versions of media and emoji -	Original Size = "original" -	// Static is the key for static (non-animated) versions of emoji -	Static Size = "static" - -	// Attachment is the key for media attachments -	Attachment Type = "attachment" -	// Header is the key for profile header requests -	Header Type = "header" -	// Avatar is the key for profile avatar requests -	Avatar Type = "avatar" -	// Emoji is the key for emoji type requests -	Emoji Type = "emoji" - -	// EmojiMaxBytes is the maximum permitted bytes of an emoji upload (50kb) -	EmojiMaxBytes = 51200 +	TypeAttachment Type = "attachment" // TypeAttachment is the key for media attachments +	TypeHeader     Type = "header"     // TypeHeader is the key for profile header requests +	TypeAvatar     Type = "avatar"     // TypeAvatar is the key for profile avatar requests +	TypeEmoji      Type = "emoji"      // TypeEmoji is the key for emoji type requests  )  // Handler provides an interface for parsing, storing, and retrieving media objects like photos, videos, and gifs. @@ -107,7 +99,7 @@ func New(database db.DB, storage *kv.KVStore) Handler {  func (mh *mediaHandler) ProcessHeaderOrAvatar(ctx context.Context, attachment []byte, accountID string, mediaType Type, remoteURL string) (*gtsmodel.MediaAttachment, error) {  	l := logrus.WithField("func", "SetHeaderForAccountID") -	if mediaType != Header && mediaType != Avatar { +	if mediaType != TypeHeader && mediaType != TypeAvatar {  		return nil, errors.New("header or avatar not selected")  	} @@ -178,8 +170,6 @@ func (mh *mediaHandler) ProcessAttachment(ctx context.Context, attachmentBytes [  // *gts.Emoji for it, then returns it to the caller. It's the caller's responsibility to put the returned struct  // in the database.  func (mh *mediaHandler) ProcessLocalEmoji(ctx context.Context, emojiBytes []byte, shortcode string) (*gtsmodel.Emoji, error) { -	keys := config.Keys -  	var clean []byte  	var err error  	var original *imageAndMeta @@ -234,31 +224,23 @@ func (mh *mediaHandler) ProcessLocalEmoji(ctx context.Context, emojiBytes []byte  	// the file extension (either png or gif)  	extension := strings.Split(contentType, "/")[1] -	// create the urls and storage paths -	serveProtocol := viper.GetString(keys.StorageServeProtocol) -	serveHost := viper.GetString(keys.StorageServeHost) -	serveBasePath := viper.GetString(keys.StorageServeBasePath) -	URLbase := fmt.Sprintf("%s://%s%s", serveProtocol, serveHost, serveBasePath) - -	// generate a id for the new emoji +	// generate a ulid for the new emoji  	newEmojiID, err := id.NewRandomULID()  	if err != nil {  		return nil, err  	} -	// webfinger uri for the emoji -- unrelated to actually serving the image -	// will be something like https://example.org/emoji/70a7f3d7-7e35-4098-8ce3-9b5e8203bb9c -	protocol := viper.GetString(keys.Protocol) -	host := viper.GetString(keys.Host) -	emojiURI := fmt.Sprintf("%s://%s/%s/%s", protocol, host, Emoji, newEmojiID) +	// activitypub uri for the emoji -- unrelated to actually serving the image +	// will be something like https://example.org/emoji/01FPSVBK3H8N7V8XK6KGSQ86EC +	emojiURI := uris.GenerateURIForEmoji(newEmojiID)  	// serve url and storage path for the original emoji -- can be png or gif -	emojiURL := fmt.Sprintf("%s/%s/%s/%s/%s.%s", URLbase, instanceAccount.ID, Emoji, Original, newEmojiID, extension) -	emojiPath := fmt.Sprintf("%s/%s/%s/%s.%s", instanceAccount.ID, Emoji, Original, newEmojiID, extension) +	emojiURL := uris.GenerateURIForAttachment(instanceAccount.ID, string(TypeEmoji), string(SizeOriginal), newEmojiID, extension) +	emojiPath := fmt.Sprintf("%s/%s/%s/%s.%s", instanceAccount.ID, TypeEmoji, SizeOriginal, newEmojiID, extension)  	// serve url and storage path for the static version -- will always be png -	emojiStaticURL := fmt.Sprintf("%s/%s/%s/%s/%s.png", URLbase, instanceAccount.ID, Emoji, Static, newEmojiID) -	emojiStaticPath := fmt.Sprintf("%s/%s/%s/%s.png", instanceAccount.ID, Emoji, Static, newEmojiID) +	emojiStaticURL := uris.GenerateURIForAttachment(instanceAccount.ID, string(TypeEmoji), string(SizeStatic), newEmojiID, "png") +	emojiStaticPath := fmt.Sprintf("%s/%s/%s/%s.png", instanceAccount.ID, TypeEmoji, SizeStatic, newEmojiID)  	// Store the original emoji  	if err := mh.storage.Put(emojiPath, original.image); err != nil { @@ -307,9 +289,9 @@ func (mh *mediaHandler) ProcessRemoteHeaderOrAvatar(ctx context.Context, t trans  	var headerOrAvi Type  	if currentAttachment.Header { -		headerOrAvi = Header +		headerOrAvi = TypeHeader  	} else if currentAttachment.Avatar { -		headerOrAvi = Avatar +		headerOrAvi = TypeAvatar  	}  	if currentAttachment.RemoteURL == "" { diff --git a/internal/media/processicon.go b/internal/media/processicon.go index 5f4f8b138..c377033fc 100644 --- a/internal/media/processicon.go +++ b/internal/media/processicon.go @@ -24,10 +24,9 @@ import (  	"strings"  	"time" -	"github.com/spf13/viper" -	"github.com/superseriousbusiness/gotosocial/internal/config"  	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"  	"github.com/superseriousbusiness/gotosocial/internal/id" +	"github.com/superseriousbusiness/gotosocial/internal/uris"  )  func (mh *mediaHandler) processHeaderOrAvi(imageBytes []byte, contentType string, mediaType Type, accountID string, remoteURL string) (*gtsmodel.MediaAttachment, error) { @@ -35,9 +34,9 @@ func (mh *mediaHandler) processHeaderOrAvi(imageBytes []byte, contentType string  	var isAvatar bool  	switch mediaType { -	case Header: +	case TypeHeader:  		isHeader = true -	case Avatar: +	case TypeAvatar:  		isAvatar = true  	default:  		return nil, errors.New("header or avatar not selected") @@ -81,23 +80,16 @@ func (mh *mediaHandler) processHeaderOrAvi(imageBytes []byte, contentType string  		return nil, err  	} -	keys := config.Keys -	serveProtocol := viper.GetString(keys.StorageServeProtocol) -	serveHost := viper.GetString(keys.StorageServeHost) -	serveBasePath := viper.GetString(keys.StorageServeBasePath) - -	URLbase := fmt.Sprintf("%s://%s%s", serveProtocol, serveHost, serveBasePath) -	originalURL := fmt.Sprintf("%s/%s/%s/original/%s.%s", URLbase, accountID, mediaType, newMediaID, extension) -	smallURL := fmt.Sprintf("%s/%s/%s/small/%s.%s", URLbase, accountID, mediaType, newMediaID, extension) - +	originalURL := uris.GenerateURIForAttachment(accountID, string(mediaType), string(SizeOriginal), newMediaID, extension) +	smallURL := uris.GenerateURIForAttachment(accountID, string(mediaType), string(SizeSmall), newMediaID, extension)  	// we store the original... -	originalPath := fmt.Sprintf("%s/%s/%s/%s.%s", accountID, mediaType, Original, newMediaID, extension) +	originalPath := fmt.Sprintf("%s/%s/%s/%s.%s", accountID, mediaType, SizeOriginal, newMediaID, extension)  	if err := mh.storage.Put(originalPath, original.image); err != nil {  		return nil, fmt.Errorf("storage error: %s", err)  	}  	// and a thumbnail... -	smallPath := fmt.Sprintf("%s/%s/%s/%s.%s", accountID, mediaType, Small, newMediaID, extension) +	smallPath := fmt.Sprintf("%s/%s/%s/%s.%s", accountID, mediaType, SizeSmall, newMediaID, extension)  	if err := mh.storage.Put(smallPath, small.image); err != nil {  		return nil, fmt.Errorf("storage error: %s", err)  	} diff --git a/internal/media/processimage.go b/internal/media/processimage.go index f3b520ad9..435ce5714 100644 --- a/internal/media/processimage.go +++ b/internal/media/processimage.go @@ -24,10 +24,9 @@ import (  	"strings"  	"time" -	"github.com/spf13/viper" -	"github.com/superseriousbusiness/gotosocial/internal/config"  	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"  	"github.com/superseriousbusiness/gotosocial/internal/id" +	"github.com/superseriousbusiness/gotosocial/internal/uris"  )  func (mh *mediaHandler) processImageAttachment(data []byte, minAttachment *gtsmodel.MediaAttachment) (*gtsmodel.MediaAttachment, error) { @@ -69,23 +68,17 @@ func (mh *mediaHandler) processImageAttachment(data []byte, minAttachment *gtsmo  		return nil, err  	} -	keys := config.Keys -	serveProtocol := viper.GetString(keys.StorageServeProtocol) -	serveHost := viper.GetString(keys.StorageServeHost) -	serveBasePath := viper.GetString(keys.StorageServeBasePath) - -	URLbase := fmt.Sprintf("%s://%s%s", serveProtocol, serveHost, serveBasePath) -	originalURL := fmt.Sprintf("%s/%s/attachment/original/%s.%s", URLbase, minAttachment.AccountID, newMediaID, extension) -	smallURL := fmt.Sprintf("%s/%s/attachment/small/%s.jpeg", URLbase, minAttachment.AccountID, newMediaID) // all thumbnails/smalls are encoded as jpeg +	originalURL := uris.GenerateURIForAttachment(minAttachment.AccountID, string(TypeAttachment), string(SizeOriginal), newMediaID, extension) +	smallURL := uris.GenerateURIForAttachment(minAttachment.AccountID, string(TypeAttachment), string(SizeSmall), newMediaID, "jpeg") // all thumbnails/smalls are encoded as jpeg  	// we store the original... -	originalPath := fmt.Sprintf("%s/%s/%s/%s.%s", minAttachment.AccountID, Attachment, Original, newMediaID, extension) +	originalPath := fmt.Sprintf("%s/%s/%s/%s.%s", minAttachment.AccountID, TypeAttachment, SizeOriginal, newMediaID, extension)  	if err := mh.storage.Put(originalPath, original.image); err != nil {  		return nil, fmt.Errorf("storage error: %s", err)  	}  	// and a thumbnail... -	smallPath := fmt.Sprintf("%s/%s/%s/%s.jpeg", minAttachment.AccountID, Attachment, Small, newMediaID) // all thumbnails/smalls are encoded as jpeg +	smallPath := fmt.Sprintf("%s/%s/%s/%s.jpeg", minAttachment.AccountID, TypeAttachment, SizeSmall, newMediaID) // all thumbnails/smalls are encoded as jpeg  	if err := mh.storage.Put(smallPath, small.image); err != nil {  		return nil, fmt.Errorf("storage error: %s", err)  	} diff --git a/internal/media/util.go b/internal/media/util.go index 963e3c93f..147178d08 100644 --- a/internal/media/util.go +++ b/internal/media/util.go @@ -295,28 +295,28 @@ type imageAndMeta struct {  // ParseMediaType converts s to a recognized MediaType, or returns an error if unrecognized  func ParseMediaType(s string) (Type, error) { -	switch Type(s) { -	case Attachment: -		return Attachment, nil -	case Header: -		return Header, nil -	case Avatar: -		return Avatar, nil -	case Emoji: -		return Emoji, nil +	switch s { +	case string(TypeAttachment): +		return TypeAttachment, nil +	case string(TypeHeader): +		return TypeHeader, nil +	case string(TypeAvatar): +		return TypeAvatar, nil +	case string(TypeEmoji): +		return TypeEmoji, nil  	}  	return "", fmt.Errorf("%s not a recognized MediaType", s)  }  // ParseMediaSize converts s to a recognized MediaSize, or returns an error if unrecognized  func ParseMediaSize(s string) (Size, error) { -	switch Size(s) { -	case Small: -		return Small, nil -	case Original: -		return Original, nil -	case Static: -		return Static, nil +	switch s { +	case string(SizeSmall): +		return SizeSmall, nil +	case string(SizeOriginal): +		return SizeOriginal, nil +	case string(SizeStatic): +		return SizeStatic, nil  	}  	return "", fmt.Errorf("%s not a recognized MediaSize", s)  } diff --git a/internal/processing/account/createblock.go b/internal/processing/account/createblock.go index 6785ffed1..bde3e00e7 100644 --- a/internal/processing/account/createblock.go +++ b/internal/processing/account/createblock.go @@ -29,7 +29,7 @@ import (  	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"  	"github.com/superseriousbusiness/gotosocial/internal/id"  	"github.com/superseriousbusiness/gotosocial/internal/messages" -	"github.com/superseriousbusiness/gotosocial/internal/util" +	"github.com/superseriousbusiness/gotosocial/internal/uris"  )  func (p *processor) BlockCreate(ctx context.Context, requestingAccount *gtsmodel.Account, targetAccountID string) (*apimodel.Relationship, gtserror.WithCode) { @@ -57,7 +57,7 @@ func (p *processor) BlockCreate(ctx context.Context, requestingAccount *gtsmodel  	block.Account = requestingAccount  	block.TargetAccountID = targetAccountID  	block.TargetAccount = targetAccount -	block.URI = util.GenerateURIForBlock(requestingAccount.Username, newBlockID) +	block.URI = uris.GenerateURIForBlock(requestingAccount.Username, newBlockID)  	// whack it in the database  	if err := p.db.Put(ctx, block); err != nil { diff --git a/internal/processing/account/createfollow.go b/internal/processing/account/createfollow.go index 9b082187b..7abce9555 100644 --- a/internal/processing/account/createfollow.go +++ b/internal/processing/account/createfollow.go @@ -29,7 +29,7 @@ import (  	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"  	"github.com/superseriousbusiness/gotosocial/internal/id"  	"github.com/superseriousbusiness/gotosocial/internal/messages" -	"github.com/superseriousbusiness/gotosocial/internal/util" +	"github.com/superseriousbusiness/gotosocial/internal/uris"  )  func (p *processor) FollowCreate(ctx context.Context, requestingAccount *gtsmodel.Account, form *apimodel.AccountFollowRequest) (*apimodel.Relationship, gtserror.WithCode) { @@ -76,7 +76,7 @@ func (p *processor) FollowCreate(ctx context.Context, requestingAccount *gtsmode  		AccountID:       requestingAccount.ID,  		TargetAccountID: form.ID,  		ShowReblogs:     true, -		URI:             util.GenerateURIForFollow(requestingAccount.Username, newFollowID), +		URI:             uris.GenerateURIForFollow(requestingAccount.Username, newFollowID),  		Notify:          false,  	}  	if form.Reblogs != nil { diff --git a/internal/processing/account/update.go b/internal/processing/account/update.go index ca386eb39..9d34f4806 100644 --- a/internal/processing/account/update.go +++ b/internal/processing/account/update.go @@ -159,7 +159,7 @@ func (p *processor) UpdateAvatar(ctx context.Context, avatar *multipart.FileHead  	}  	// do the setting -	avatarInfo, err := p.mediaHandler.ProcessHeaderOrAvatar(ctx, buf.Bytes(), accountID, media.Avatar, "") +	avatarInfo, err := p.mediaHandler.ProcessHeaderOrAvatar(ctx, buf.Bytes(), accountID, media.TypeAvatar, "")  	if err != nil {  		return nil, fmt.Errorf("error processing avatar: %s", err)  	} @@ -193,7 +193,7 @@ func (p *processor) UpdateHeader(ctx context.Context, header *multipart.FileHead  	}  	// do the setting -	headerInfo, err := p.mediaHandler.ProcessHeaderOrAvatar(ctx, buf.Bytes(), accountID, media.Header, "") +	headerInfo, err := p.mediaHandler.ProcessHeaderOrAvatar(ctx, buf.Bytes(), accountID, media.TypeHeader, "")  	if err != nil {  		return nil, fmt.Errorf("error processing header: %s", err)  	} diff --git a/internal/processing/federation/getuser.go b/internal/processing/federation/getuser.go index bde3d58de..9f2201c1c 100644 --- a/internal/processing/federation/getuser.go +++ b/internal/processing/federation/getuser.go @@ -27,7 +27,7 @@ import (  	"github.com/superseriousbusiness/activity/streams"  	"github.com/superseriousbusiness/activity/streams/vocab"  	"github.com/superseriousbusiness/gotosocial/internal/gtserror" -	"github.com/superseriousbusiness/gotosocial/internal/util" +	"github.com/superseriousbusiness/gotosocial/internal/uris"  )  func (p *processor) GetUser(ctx context.Context, requestedUsername string, requestURL *url.URL) (interface{}, gtserror.WithCode) { @@ -39,13 +39,13 @@ func (p *processor) GetUser(ctx context.Context, requestedUsername string, reque  	var requestedPerson vocab.ActivityStreamsPerson  	switch { -	case util.IsPublicKeyPath(requestURL): +	case uris.IsPublicKeyPath(requestURL):  		// if it's a public key path, we don't need to authenticate but we'll only serve the bare minimum user profile needed for the public key  		requestedPerson, err = p.tc.AccountToASMinimal(ctx, requestedAccount)  		if err != nil {  			return nil, gtserror.NewErrorInternalError(err)  		} -	case util.IsUserPath(requestURL): +	case uris.IsUserPath(requestURL):  		// if it's a user path, we want to fully authenticate the request before we serve any data, and then we can serve a more complete profile  		requestingAccountURI, authenticated, err := p.federator.AuthenticateFederatedRequest(ctx, requestedUsername)  		if err != nil || !authenticated { diff --git a/internal/processing/federation/postinbox.go b/internal/processing/federation/postinbox.go index df9da0a51..e2143bf46 100644 --- a/internal/processing/federation/postinbox.go +++ b/internal/processing/federation/postinbox.go @@ -22,11 +22,11 @@ import (  	"context"  	"net/http" -	"github.com/superseriousbusiness/gotosocial/internal/util" +	"github.com/superseriousbusiness/gotosocial/internal/ap"  )  func (p *processor) PostInbox(ctx context.Context, w http.ResponseWriter, r *http.Request) (bool, error) {  	// pass the fromFederator channel through to postInbox, since it'll be needed later -	contextWithChannel := context.WithValue(ctx, util.APFromFederatorChanKey, p.fromFederator) +	contextWithChannel := context.WithValue(ctx, ap.ContextFromFederatorChan, p.fromFederator)  	return p.federator.FederatingActor().PostInbox(contextWithChannel, w, r)  } diff --git a/internal/processing/media/getfile.go b/internal/processing/media/getfile.go index 3cfdbe56b..52ea04484 100644 --- a/internal/processing/media/getfile.go +++ b/internal/processing/media/getfile.go @@ -72,7 +72,7 @@ func (p *processor) GetFile(ctx context.Context, account *gtsmodel.Account, form  	content := &apimodel.Content{}  	var storagePath string  	switch mediaType { -	case media.Emoji: +	case media.TypeEmoji:  		e := >smodel.Emoji{}  		if err := p.db.GetByID(ctx, wantedMediaID, e); err != nil {  			return nil, gtserror.NewErrorNotFound(fmt.Errorf("emoji %s could not be taken from the db: %s", wantedMediaID, err)) @@ -81,16 +81,16 @@ func (p *processor) GetFile(ctx context.Context, account *gtsmodel.Account, form  			return nil, gtserror.NewErrorNotFound(fmt.Errorf("emoji %s has been disabled", wantedMediaID))  		}  		switch mediaSize { -		case media.Original: +		case media.SizeOriginal:  			content.ContentType = e.ImageContentType  			storagePath = e.ImagePath -		case media.Static: +		case media.SizeStatic:  			content.ContentType = e.ImageStaticContentType  			storagePath = e.ImageStaticPath  		default:  			return nil, gtserror.NewErrorNotFound(fmt.Errorf("media size %s not recognized for emoji", mediaSize))  		} -	case media.Attachment, media.Header, media.Avatar: +	case media.TypeAttachment, media.TypeHeader, media.TypeAvatar:  		a, err := p.db.GetAttachmentByID(ctx, wantedMediaID)  		if err != nil {  			return nil, gtserror.NewErrorNotFound(fmt.Errorf("attachment %s could not be taken from the db: %s", wantedMediaID, err)) @@ -99,10 +99,10 @@ func (p *processor) GetFile(ctx context.Context, account *gtsmodel.Account, form  			return nil, gtserror.NewErrorNotFound(fmt.Errorf("attachment %s is not owned by %s", wantedMediaID, form.AccountID))  		}  		switch mediaSize { -		case media.Original: +		case media.SizeOriginal:  			content.ContentType = a.File.ContentType  			storagePath = a.File.Path -		case media.Small: +		case media.SizeSmall:  			content.ContentType = a.Thumbnail.ContentType  			storagePath = a.Thumbnail.Path  		default: diff --git a/internal/processing/status/create.go b/internal/processing/status/create.go index 9bcb32b78..d1bd82b28 100644 --- a/internal/processing/status/create.go +++ b/internal/processing/status/create.go @@ -30,17 +30,17 @@ import (  	"github.com/superseriousbusiness/gotosocial/internal/id"  	"github.com/superseriousbusiness/gotosocial/internal/messages"  	"github.com/superseriousbusiness/gotosocial/internal/text" -	"github.com/superseriousbusiness/gotosocial/internal/util" +	"github.com/superseriousbusiness/gotosocial/internal/uris"  )  func (p *processor) Create(ctx context.Context, account *gtsmodel.Account, application *gtsmodel.Application, form *apimodel.AdvancedStatusCreateForm) (*apimodel.Status, gtserror.WithCode) { -	uris := util.GenerateURIsForAccount(account.Username) +	accountURIs := uris.GenerateURIsForAccount(account.Username)  	thisStatusID, err := id.NewULID()  	if err != nil {  		return nil, gtserror.NewErrorInternalError(err)  	} -	thisStatusURI := fmt.Sprintf("%s/%s", uris.StatusesURI, thisStatusID) -	thisStatusURL := fmt.Sprintf("%s/%s", uris.StatusesURL, thisStatusID) +	thisStatusURI := fmt.Sprintf("%s/%s", accountURIs.StatusesURI, thisStatusID) +	thisStatusURL := fmt.Sprintf("%s/%s", accountURIs.StatusesURL, thisStatusID)  	newStatus := >smodel.Status{  		ID:                       thisStatusID, diff --git a/internal/processing/status/fave.go b/internal/processing/status/fave.go index 581caf055..a044a2b58 100644 --- a/internal/processing/status/fave.go +++ b/internal/processing/status/fave.go @@ -30,7 +30,7 @@ import (  	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"  	"github.com/superseriousbusiness/gotosocial/internal/id"  	"github.com/superseriousbusiness/gotosocial/internal/messages" -	"github.com/superseriousbusiness/gotosocial/internal/util" +	"github.com/superseriousbusiness/gotosocial/internal/uris"  )  func (p *processor) Fave(ctx context.Context, requestingAccount *gtsmodel.Account, targetStatusID string) (*apimodel.Status, gtserror.WithCode) { @@ -76,7 +76,7 @@ func (p *processor) Fave(ctx context.Context, requestingAccount *gtsmodel.Accoun  			TargetAccount:   targetStatus.Account,  			StatusID:        targetStatus.ID,  			Status:          targetStatus, -			URI:             util.GenerateURIForLike(requestingAccount.Username, thisFaveID), +			URI:             uris.GenerateURIForLike(requestingAccount.Username, thisFaveID),  		}  		if err := p.db.Put(ctx, gtsFave); err != nil { diff --git a/internal/processing/user/emailconfirm.go b/internal/processing/user/emailconfirm.go index 3e19c61d4..4a588c395 100644 --- a/internal/processing/user/emailconfirm.go +++ b/internal/processing/user/emailconfirm.go @@ -31,7 +31,7 @@ import (  	"github.com/superseriousbusiness/gotosocial/internal/email"  	"github.com/superseriousbusiness/gotosocial/internal/gtserror"  	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" -	"github.com/superseriousbusiness/gotosocial/internal/util" +	"github.com/superseriousbusiness/gotosocial/internal/uris"  )  var ( @@ -53,7 +53,7 @@ func (p *processor) SendConfirmEmail(ctx context.Context, user *gtsmodel.User, u  	//      equivalent to the odds of creating a few tens of trillions of UUIDs in a  	//      year and having one duplicate.  	confirmationToken := uuid.NewString() -	confirmationLink := util.GenerateURIForEmailConfirm(confirmationToken) +	confirmationLink := uris.GenerateURIForEmailConfirm(confirmationToken)  	// pull our instance entry from the database so we can greet the user nicely in the email  	instance := >smodel.Instance{} diff --git a/internal/typeutils/internal.go b/internal/typeutils/internal.go index 2257d7203..0d49ea6b2 100644 --- a/internal/typeutils/internal.go +++ b/internal/typeutils/internal.go @@ -7,7 +7,7 @@ import (  	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"  	"github.com/superseriousbusiness/gotosocial/internal/id" -	"github.com/superseriousbusiness/gotosocial/internal/util" +	"github.com/superseriousbusiness/gotosocial/internal/uris"  )  func (c *converter) FollowRequestToFollow(ctx context.Context, f *gtsmodel.FollowRequest) *gtsmodel.Follow { @@ -25,13 +25,13 @@ func (c *converter) FollowRequestToFollow(ctx context.Context, f *gtsmodel.Follo  func (c *converter) StatusToBoost(ctx context.Context, s *gtsmodel.Status, boostingAccount *gtsmodel.Account) (*gtsmodel.Status, error) {  	// the wrapper won't use the same ID as the boosted status so we generate some new UUIDs -	uris := util.GenerateURIsForAccount(boostingAccount.Username) +	accountURIs := uris.GenerateURIsForAccount(boostingAccount.Username)  	boostWrapperStatusID, err := id.NewULID()  	if err != nil {  		return nil, err  	} -	boostWrapperStatusURI := fmt.Sprintf("%s/%s", uris.StatusesURI, boostWrapperStatusID) -	boostWrapperStatusURL := fmt.Sprintf("%s/%s", uris.StatusesURL, boostWrapperStatusID) +	boostWrapperStatusURI := fmt.Sprintf("%s/%s", accountURIs.StatusesURI, boostWrapperStatusID) +	boostWrapperStatusURL := fmt.Sprintf("%s/%s", accountURIs.StatusesURL, boostWrapperStatusID)  	local := true  	if boostingAccount.Domain != "" { diff --git a/internal/typeutils/wrap.go b/internal/typeutils/wrap.go index 0f82a679b..81e8e53de 100644 --- a/internal/typeutils/wrap.go +++ b/internal/typeutils/wrap.go @@ -10,7 +10,7 @@ import (  	"github.com/superseriousbusiness/gotosocial/internal/ap"  	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"  	"github.com/superseriousbusiness/gotosocial/internal/id" -	"github.com/superseriousbusiness/gotosocial/internal/util" +	"github.com/superseriousbusiness/gotosocial/internal/uris"  )  func (c *converter) WrapPersonInUpdate(person vocab.ActivityStreamsPerson, originAccount *gtsmodel.Account) (vocab.ActivityStreamsUpdate, error) { @@ -33,7 +33,7 @@ func (c *converter) WrapPersonInUpdate(person vocab.ActivityStreamsPerson, origi  		return nil, err  	} -	idString := util.GenerateURIForUpdate(originAccount.Username, newID) +	idString := uris.GenerateURIForUpdate(originAccount.Username, newID)  	idURI, err := url.Parse(idString)  	if err != nil {  		return nil, fmt.Errorf("WrapPersonInUpdate: error parsing url %s: %s", idString, err) diff --git a/internal/util/uri.go b/internal/uris/uri.go index b9ef01799..2b52dc6ce 100644 --- a/internal/util/uri.go +++ b/internal/uris/uri.go @@ -16,7 +16,7 @@     along with this program.  If not, see <http://www.gnu.org/licenses/>.  */ -package util +package uris  import (  	"fmt" @@ -28,65 +28,25 @@ import (  )  const ( -	// UsersPath is for serving users info -	UsersPath = "users" -	// ActorsPath is for serving actors info -	ActorsPath = "actors" -	// StatusesPath is for serving statuses -	StatusesPath = "statuses" -	// InboxPath represents the webfinger inbox location -	InboxPath = "inbox" -	// OutboxPath represents the webfinger outbox location -	OutboxPath = "outbox" -	// FollowersPath represents the webfinger followers location -	FollowersPath = "followers" -	// FollowingPath represents the webfinger following location -	FollowingPath = "following" -	// LikedPath represents the webfinger liked location -	LikedPath = "liked" -	// CollectionsPath represents the webfinger collections location -	CollectionsPath = "collections" -	// FeaturedPath represents the webfinger featured location -	FeaturedPath = "featured" -	// PublicKeyPath is for serving an account's public key -	PublicKeyPath = "main-key" -	// FollowPath used to generate the URI for an individual follow or follow request -	FollowPath = "follow" -	// UpdatePath is used to generate the URI for an account update -	UpdatePath = "updates" -	// BlocksPath is used to generate the URI for a block -	BlocksPath = "blocks" -	// ConfirmEmailPath is used to generate the URI for an email confirmation link -	ConfirmEmailPath = "confirm_email" +	UsersPath        = "users"         // UsersPath is for serving users info +	ActorsPath       = "actors"        // ActorsPath is for serving actors info +	StatusesPath     = "statuses"      // StatusesPath is for serving statuses +	InboxPath        = "inbox"         // InboxPath represents the activitypub inbox location +	OutboxPath       = "outbox"        // OutboxPath represents the activitypub outbox location +	FollowersPath    = "followers"     // FollowersPath represents the activitypub followers location +	FollowingPath    = "following"     // FollowingPath represents the activitypub following location +	LikedPath        = "liked"         // LikedPath represents the activitypub liked location +	CollectionsPath  = "collections"   // CollectionsPath represents the activitypub collections location +	FeaturedPath     = "featured"      // FeaturedPath represents the activitypub featured location +	PublicKeyPath    = "main-key"      // PublicKeyPath is for serving an account's public key +	FollowPath       = "follow"        // FollowPath used to generate the URI for an individual follow or follow request +	UpdatePath       = "updates"       // UpdatePath is used to generate the URI for an account update +	BlocksPath       = "blocks"        // BlocksPath is used to generate the URI for a block +	ConfirmEmailPath = "confirm_email" // ConfirmEmailPath is used to generate the URI for an email confirmation link +	FileserverPath   = "fileserver"    // FileserverPath is a path component for serving attachments + media +	EmojiPath        = "emoji"         // EmojiPath represents the activitypub emoji location  ) -// APContextKey is a type used specifically for settings values on contexts within go-fed AP request chains -type APContextKey string - -const ( -	// APActivity can be used to set and retrieve the actual go-fed pub.Activity within a context. -	APActivity APContextKey = "activity" -	// APReceivingAccount can be used the set and retrieve the account being interacted with / receiving an activity in their inbox. -	APReceivingAccount APContextKey = "account" -	// APRequestingAccount can be used to set and retrieve the account of an incoming federation request. -	// This will often be the actor of the instance that's posting the request. -	APRequestingAccount APContextKey = "requestingAccount" -	// APRequestingActorIRI can be used to set and retrieve the actor of an incoming federation request. -	// This will usually be the owner of whatever activity is being posted. -	APRequestingActorIRI APContextKey = "requestingActorIRI" -	// APRequestingPublicKeyVerifier can be used to set and retrieve the public key verifier of an incoming federation request. -	APRequestingPublicKeyVerifier APContextKey = "requestingPublicKeyVerifier" -	// APRequestingPublicKeySignature can be used to set and retrieve the value of the signature header of an incoming federation request. -	APRequestingPublicKeySignature APContextKey = "requestingPublicKeySignature" -	// APFromFederatorChanKey can be used to pass a pointer to the fromFederator channel into the federator for use in callbacks. -	APFromFederatorChanKey APContextKey = "fromFederatorChan" -) - -type ginContextKey struct{} - -// GinContextKey is used solely for setting and retrieving the gin context from a context.Context -var GinContextKey = &ginContextKey{} -  // UserURIs contains a bunch of UserURIs and URLs for a user, host, account, etc.  type UserURIs struct {  	// The web URL of the instance host, eg https://example.org @@ -96,21 +56,21 @@ type UserURIs struct {  	// The web URL for statuses of this user, eg., https://example.org/@example_user/statuses  	StatusesURL string -	// The webfinger URI of this user, eg., https://example.org/users/example_user +	// The activitypub URI of this user, eg., https://example.org/users/example_user  	UserURI string -	// The webfinger URI for this user's statuses, eg., https://example.org/users/example_user/statuses +	// The activitypub URI for this user's statuses, eg., https://example.org/users/example_user/statuses  	StatusesURI string -	// The webfinger URI for this user's activitypub inbox, eg., https://example.org/users/example_user/inbox +	// The activitypub URI for this user's activitypub inbox, eg., https://example.org/users/example_user/inbox  	InboxURI string -	// The webfinger URI for this user's activitypub outbox, eg., https://example.org/users/example_user/outbox +	// The activitypub URI for this user's activitypub outbox, eg., https://example.org/users/example_user/outbox  	OutboxURI string -	// The webfinger URI for this user's followers, eg., https://example.org/users/example_user/followers +	// The activitypub URI for this user's followers, eg., https://example.org/users/example_user/followers  	FollowersURI string -	// The webfinger URI for this user's following, eg., https://example.org/users/example_user/following +	// The activitypub URI for this user's following, eg., https://example.org/users/example_user/following  	FollowingURI string -	// The webfinger URI for this user's liked posts eg., https://example.org/users/example_user/liked +	// The activitypub URI for this user's liked posts eg., https://example.org/users/example_user/liked  	LikedURI string -	// The webfinger URI for this user's featured collections, eg., https://example.org/users/example_user/collections/featured +	// The activitypub URI for this user's featured collections, eg., https://example.org/users/example_user/collections/featured  	CollectionURI string  	// The URI for this user's public key, eg., https://example.org/users/example_user/publickey  	PublicKeyURI string @@ -194,6 +154,23 @@ func GenerateURIsForAccount(username string) *UserURIs {  	}  } +// GenerateURIForAttachment generates a URI for an attachment/emoji/header etc. +// Will produced something like https://example.org/fileserver/01FPST95B8FC3HG3AGCDKPQNQ2/attachment/original/01FPST9QK4V5XWS3F9Z4F2G1X7.gif +func GenerateURIForAttachment(accountID string, mediaType string, mediaSize string, mediaID string, extension string) string { +	protocol := viper.GetString(config.Keys.Protocol) +	host := viper.GetString(config.Keys.Host) + +	return fmt.Sprintf("%s://%s/%s/%s/%s/%s/%s.%s", protocol, host, FileserverPath, accountID, mediaType, mediaSize, mediaID, extension) +} + +// GenerateURIForEmoji generates an activitypub uri for a new emoji. +func GenerateURIForEmoji(emojiID string) string { +	protocol := viper.GetString(config.Keys.Protocol) +	host := viper.GetString(config.Keys.Host) + +	return fmt.Sprintf("%s://%s/%s/%s", protocol, host, EmojiPath, emojiID) +} +  // IsUserPath returns true if the given URL path corresponds to eg /users/example_username  func IsUserPath(id *url.URL) bool {  	return regexes.UserPath.MatchString(id.Path) diff --git a/internal/web/base.go b/internal/web/base.go index 9d99fddd1..e2f3b769e 100644 --- a/internal/web/base.go +++ b/internal/web/base.go @@ -31,11 +31,11 @@ import (  	"github.com/superseriousbusiness/gotosocial/internal/config"  	"github.com/superseriousbusiness/gotosocial/internal/processing"  	"github.com/superseriousbusiness/gotosocial/internal/router" -	"github.com/superseriousbusiness/gotosocial/internal/util" +	"github.com/superseriousbusiness/gotosocial/internal/uris"  )  const ( -	confirmEmailPath = "/" + util.ConfirmEmailPath +	confirmEmailPath = "/" + uris.ConfirmEmailPath  	tokenParam       = "token"  ) diff --git a/test/cliparsing.sh b/test/cliparsing.sh index 364ae8ab0..20d736b4f 100755 --- a/test/cliparsing.sh +++ b/test/cliparsing.sh @@ -5,7 +5,7 @@ set -e  echo "STARTING CLI TESTS"  echo "TEST_1 Make sure defaults are set correctly." -TEST_1_EXPECTED='{"account-domain":"","accounts-approval-required":true,"accounts-reason-required":true,"accounts-registration-open":true,"application-name":"gotosocial","bind-address":"0.0.0.0","config-path":"","db-address":"localhost","db-database":"postgres","db-password":"postgres","db-port":5432,"db-tls-ca-cert":"","db-tls-mode":"disable","db-type":"postgres","db-user":"postgres","help":false,"host":"","letsencrypt-cert-dir":"/gotosocial/storage/certs","letsencrypt-email-address":"","letsencrypt-enabled":true,"letsencrypt-port":80,"log-level":"info","media-description-max-chars":500,"media-description-min-chars":0,"media-image-max-size":2097152,"media-video-max-size":10485760,"oidc-client-id":"","oidc-client-secret":"","oidc-enabled":false,"oidc-idp-name":"","oidc-issuer":"","oidc-scopes":["openid","profile","email","groups"],"oidc-skip-verification":false,"port":8080,"protocol":"https","smtp-from":"GoToSocial","smtp-host":"","smtp-password":"","smtp-port":0,"smtp-username":"","software-version":"","statuses-cw-max-chars":100,"statuses-max-chars":5000,"statuses-media-max-files":6,"statuses-poll-max-options":6,"statuses-poll-option-max-chars":50,"storage-backend":"local","storage-base-path":"/gotosocial/storage","storage-serve-base-path":"/fileserver","storage-serve-host":"localhost","storage-serve-protocol":"https","syslog-address":"localhost:514","syslog-enabled":false,"syslog-protocol":"udp","trusted-proxies":["127.0.0.1/32"],"web-asset-base-dir":"./web/assets/","web-template-base-dir":"./web/template/"}' +TEST_1_EXPECTED='{"account-domain":"","accounts-approval-required":true,"accounts-reason-required":true,"accounts-registration-open":true,"application-name":"gotosocial","bind-address":"0.0.0.0","config-path":"","db-address":"localhost","db-database":"postgres","db-password":"postgres","db-port":5432,"db-tls-ca-cert":"","db-tls-mode":"disable","db-type":"postgres","db-user":"postgres","help":false,"host":"","letsencrypt-cert-dir":"/gotosocial/storage/certs","letsencrypt-email-address":"","letsencrypt-enabled":true,"letsencrypt-port":80,"log-level":"info","media-description-max-chars":500,"media-description-min-chars":0,"media-image-max-size":2097152,"media-video-max-size":10485760,"oidc-client-id":"","oidc-client-secret":"","oidc-enabled":false,"oidc-idp-name":"","oidc-issuer":"","oidc-scopes":["openid","profile","email","groups"],"oidc-skip-verification":false,"port":8080,"protocol":"https","smtp-from":"GoToSocial","smtp-host":"","smtp-password":"","smtp-port":0,"smtp-username":"","software-version":"","statuses-cw-max-chars":100,"statuses-max-chars":5000,"statuses-media-max-files":6,"statuses-poll-max-options":6,"statuses-poll-option-max-chars":50,"storage-backend":"local","storage-local-base-path":"/gotosocial/storage","syslog-address":"localhost:514","syslog-enabled":false,"syslog-protocol":"udp","trusted-proxies":["127.0.0.1/32"],"web-asset-base-dir":"./web/assets/","web-template-base-dir":"./web/template/"}'  TEST_1="$(go run ./cmd/gotosocial/... debug config)"  if [ "${TEST_1}" != "${TEST_1_EXPECTED}" ]; then      echo "TEST_1 not equal TEST_1_EXPECTED" @@ -15,7 +15,7 @@ else  fi  echo "TEST_2 Override db-address from default using cli flag." -TEST_2_EXPECTED='{"account-domain":"","accounts-approval-required":true,"accounts-reason-required":true,"accounts-registration-open":true,"application-name":"gotosocial","bind-address":"0.0.0.0","config-path":"","db-address":"some.db.address","db-database":"postgres","db-password":"postgres","db-port":5432,"db-tls-ca-cert":"","db-tls-mode":"disable","db-type":"postgres","db-user":"postgres","help":false,"host":"","letsencrypt-cert-dir":"/gotosocial/storage/certs","letsencrypt-email-address":"","letsencrypt-enabled":true,"letsencrypt-port":80,"log-level":"info","media-description-max-chars":500,"media-description-min-chars":0,"media-image-max-size":2097152,"media-video-max-size":10485760,"oidc-client-id":"","oidc-client-secret":"","oidc-enabled":false,"oidc-idp-name":"","oidc-issuer":"","oidc-scopes":["openid","profile","email","groups"],"oidc-skip-verification":false,"port":8080,"protocol":"https","smtp-from":"GoToSocial","smtp-host":"","smtp-password":"","smtp-port":0,"smtp-username":"","software-version":"","statuses-cw-max-chars":100,"statuses-max-chars":5000,"statuses-media-max-files":6,"statuses-poll-max-options":6,"statuses-poll-option-max-chars":50,"storage-backend":"local","storage-base-path":"/gotosocial/storage","storage-serve-base-path":"/fileserver","storage-serve-host":"localhost","storage-serve-protocol":"https","syslog-address":"localhost:514","syslog-enabled":false,"syslog-protocol":"udp","trusted-proxies":["127.0.0.1/32"],"web-asset-base-dir":"./web/assets/","web-template-base-dir":"./web/template/"}' +TEST_2_EXPECTED='{"account-domain":"","accounts-approval-required":true,"accounts-reason-required":true,"accounts-registration-open":true,"application-name":"gotosocial","bind-address":"0.0.0.0","config-path":"","db-address":"some.db.address","db-database":"postgres","db-password":"postgres","db-port":5432,"db-tls-ca-cert":"","db-tls-mode":"disable","db-type":"postgres","db-user":"postgres","help":false,"host":"","letsencrypt-cert-dir":"/gotosocial/storage/certs","letsencrypt-email-address":"","letsencrypt-enabled":true,"letsencrypt-port":80,"log-level":"info","media-description-max-chars":500,"media-description-min-chars":0,"media-image-max-size":2097152,"media-video-max-size":10485760,"oidc-client-id":"","oidc-client-secret":"","oidc-enabled":false,"oidc-idp-name":"","oidc-issuer":"","oidc-scopes":["openid","profile","email","groups"],"oidc-skip-verification":false,"port":8080,"protocol":"https","smtp-from":"GoToSocial","smtp-host":"","smtp-password":"","smtp-port":0,"smtp-username":"","software-version":"","statuses-cw-max-chars":100,"statuses-max-chars":5000,"statuses-media-max-files":6,"statuses-poll-max-options":6,"statuses-poll-option-max-chars":50,"storage-backend":"local","storage-local-base-path":"/gotosocial/storage","syslog-address":"localhost:514","syslog-enabled":false,"syslog-protocol":"udp","trusted-proxies":["127.0.0.1/32"],"web-asset-base-dir":"./web/assets/","web-template-base-dir":"./web/template/"}'  TEST_2="$(go run ./cmd/gotosocial/... --db-address some.db.address debug config)"  if [ "${TEST_2}" != "${TEST_2_EXPECTED}" ]; then      echo "TEST_2 not equal TEST_2_EXPECTED" @@ -25,7 +25,7 @@ else  fi  echo "TEST_3 Override db-address from default using env var." -TEST_3_EXPECTED='{"account-domain":"","accounts-approval-required":true,"accounts-reason-required":true,"accounts-registration-open":true,"application-name":"gotosocial","bind-address":"0.0.0.0","config-path":"","db-address":"some.db.address","db-database":"postgres","db-password":"postgres","db-port":5432,"db-tls-ca-cert":"","db-tls-mode":"disable","db-type":"postgres","db-user":"postgres","help":false,"host":"","letsencrypt-cert-dir":"/gotosocial/storage/certs","letsencrypt-email-address":"","letsencrypt-enabled":true,"letsencrypt-port":80,"log-level":"info","media-description-max-chars":500,"media-description-min-chars":0,"media-image-max-size":2097152,"media-video-max-size":10485760,"oidc-client-id":"","oidc-client-secret":"","oidc-enabled":false,"oidc-idp-name":"","oidc-issuer":"","oidc-scopes":["openid","profile","email","groups"],"oidc-skip-verification":false,"port":8080,"protocol":"https","smtp-from":"GoToSocial","smtp-host":"","smtp-password":"","smtp-port":0,"smtp-username":"","software-version":"","statuses-cw-max-chars":100,"statuses-max-chars":5000,"statuses-media-max-files":6,"statuses-poll-max-options":6,"statuses-poll-option-max-chars":50,"storage-backend":"local","storage-base-path":"/gotosocial/storage","storage-serve-base-path":"/fileserver","storage-serve-host":"localhost","storage-serve-protocol":"https","syslog-address":"localhost:514","syslog-enabled":false,"syslog-protocol":"udp","trusted-proxies":["127.0.0.1/32"],"web-asset-base-dir":"./web/assets/","web-template-base-dir":"./web/template/"}' +TEST_3_EXPECTED='{"account-domain":"","accounts-approval-required":true,"accounts-reason-required":true,"accounts-registration-open":true,"application-name":"gotosocial","bind-address":"0.0.0.0","config-path":"","db-address":"some.db.address","db-database":"postgres","db-password":"postgres","db-port":5432,"db-tls-ca-cert":"","db-tls-mode":"disable","db-type":"postgres","db-user":"postgres","help":false,"host":"","letsencrypt-cert-dir":"/gotosocial/storage/certs","letsencrypt-email-address":"","letsencrypt-enabled":true,"letsencrypt-port":80,"log-level":"info","media-description-max-chars":500,"media-description-min-chars":0,"media-image-max-size":2097152,"media-video-max-size":10485760,"oidc-client-id":"","oidc-client-secret":"","oidc-enabled":false,"oidc-idp-name":"","oidc-issuer":"","oidc-scopes":["openid","profile","email","groups"],"oidc-skip-verification":false,"port":8080,"protocol":"https","smtp-from":"GoToSocial","smtp-host":"","smtp-password":"","smtp-port":0,"smtp-username":"","software-version":"","statuses-cw-max-chars":100,"statuses-max-chars":5000,"statuses-media-max-files":6,"statuses-poll-max-options":6,"statuses-poll-option-max-chars":50,"storage-backend":"local","storage-local-base-path":"/gotosocial/storage","syslog-address":"localhost:514","syslog-enabled":false,"syslog-protocol":"udp","trusted-proxies":["127.0.0.1/32"],"web-asset-base-dir":"./web/assets/","web-template-base-dir":"./web/template/"}'  TEST_3="$(GTS_DB_ADDRESS=some.db.address go run ./cmd/gotosocial/... debug config)"  if [ "${TEST_3}" != "${TEST_3_EXPECTED}" ]; then      echo "TEST_3 not equal TEST_3_EXPECTED" @@ -35,7 +35,7 @@ else  fi  echo "TEST_4 Override db-address from default using both env var and cli flag. The cli flag should take priority." -TEST_4_EXPECTED='{"account-domain":"","accounts-approval-required":true,"accounts-reason-required":true,"accounts-registration-open":true,"application-name":"gotosocial","bind-address":"0.0.0.0","config-path":"","db-address":"some.other.db.address","db-database":"postgres","db-password":"postgres","db-port":5432,"db-tls-ca-cert":"","db-tls-mode":"disable","db-type":"postgres","db-user":"postgres","help":false,"host":"","letsencrypt-cert-dir":"/gotosocial/storage/certs","letsencrypt-email-address":"","letsencrypt-enabled":true,"letsencrypt-port":80,"log-level":"info","media-description-max-chars":500,"media-description-min-chars":0,"media-image-max-size":2097152,"media-video-max-size":10485760,"oidc-client-id":"","oidc-client-secret":"","oidc-enabled":false,"oidc-idp-name":"","oidc-issuer":"","oidc-scopes":["openid","profile","email","groups"],"oidc-skip-verification":false,"port":8080,"protocol":"https","smtp-from":"GoToSocial","smtp-host":"","smtp-password":"","smtp-port":0,"smtp-username":"","software-version":"","statuses-cw-max-chars":100,"statuses-max-chars":5000,"statuses-media-max-files":6,"statuses-poll-max-options":6,"statuses-poll-option-max-chars":50,"storage-backend":"local","storage-base-path":"/gotosocial/storage","storage-serve-base-path":"/fileserver","storage-serve-host":"localhost","storage-serve-protocol":"https","syslog-address":"localhost:514","syslog-enabled":false,"syslog-protocol":"udp","trusted-proxies":["127.0.0.1/32"],"web-asset-base-dir":"./web/assets/","web-template-base-dir":"./web/template/"}' +TEST_4_EXPECTED='{"account-domain":"","accounts-approval-required":true,"accounts-reason-required":true,"accounts-registration-open":true,"application-name":"gotosocial","bind-address":"0.0.0.0","config-path":"","db-address":"some.other.db.address","db-database":"postgres","db-password":"postgres","db-port":5432,"db-tls-ca-cert":"","db-tls-mode":"disable","db-type":"postgres","db-user":"postgres","help":false,"host":"","letsencrypt-cert-dir":"/gotosocial/storage/certs","letsencrypt-email-address":"","letsencrypt-enabled":true,"letsencrypt-port":80,"log-level":"info","media-description-max-chars":500,"media-description-min-chars":0,"media-image-max-size":2097152,"media-video-max-size":10485760,"oidc-client-id":"","oidc-client-secret":"","oidc-enabled":false,"oidc-idp-name":"","oidc-issuer":"","oidc-scopes":["openid","profile","email","groups"],"oidc-skip-verification":false,"port":8080,"protocol":"https","smtp-from":"GoToSocial","smtp-host":"","smtp-password":"","smtp-port":0,"smtp-username":"","software-version":"","statuses-cw-max-chars":100,"statuses-max-chars":5000,"statuses-media-max-files":6,"statuses-poll-max-options":6,"statuses-poll-option-max-chars":50,"storage-backend":"local","storage-local-base-path":"/gotosocial/storage","syslog-address":"localhost:514","syslog-enabled":false,"syslog-protocol":"udp","trusted-proxies":["127.0.0.1/32"],"web-asset-base-dir":"./web/assets/","web-template-base-dir":"./web/template/"}'  TEST_4="$(GTS_DB_ADDRESS=some.db.address go run ./cmd/gotosocial/... --db-address some.other.db.address debug config)"  if [ "${TEST_4}" != "${TEST_4_EXPECTED}" ]; then      echo "TEST_4 not equal TEST_4_EXPECTED" @@ -45,7 +45,7 @@ else  fi  echo "TEST_5 Test loading a config file by passing an env var." -TEST_5_EXPECTED='{"account-domain":"example.org","accounts-approval-required":true,"accounts-reason-required":true,"accounts-registration-open":true,"application-name":"gotosocial","bind-address":"0.0.0.0","config-path":"./test/test.yaml","db-address":"127.0.0.1","db-database":"postgres","db-password":"postgres","db-port":5432,"db-tls-ca-cert":"","db-tls-mode":"disable","db-type":"postgres","db-user":"postgres","help":false,"host":"gts.example.org","letsencrypt-cert-dir":"/gotosocial/storage/certs","letsencrypt-email-address":"","letsencrypt-enabled":true,"letsencrypt-port":80,"log-level":"info","media-description-max-chars":500,"media-description-min-chars":0,"media-image-max-size":2097152,"media-video-max-size":10485760,"oidc-client-id":"","oidc-client-secret":"","oidc-enabled":false,"oidc-idp-name":"","oidc-issuer":"","oidc-scopes":["openid","email","profile","groups"],"oidc-skip-verification":false,"port":8080,"protocol":"https","smtp-from":"someone@example.org","smtp-host":"verycoolemailhost.mail","smtp-password":"smtp-password","smtp-port":8888,"smtp-username":"smtp-username","software-version":"","statuses-cw-max-chars":100,"statuses-max-chars":5000,"statuses-media-max-files":6,"statuses-poll-max-options":6,"statuses-poll-option-max-chars":50,"storage-backend":"local","storage-base-path":"/gotosocial/storage","storage-serve-base-path":"/fileserver","storage-serve-host":"localhost","storage-serve-protocol":"https","syslog-address":"localhost:514","syslog-enabled":false,"syslog-protocol":"udp","trusted-proxies":["127.0.0.1/32","0.0.0.0/0"],"web-asset-base-dir":"./web/assets/","web-template-base-dir":"./web/template/"}' +TEST_5_EXPECTED='{"account-domain":"example.org","accounts-approval-required":true,"accounts-reason-required":true,"accounts-registration-open":true,"application-name":"gotosocial","bind-address":"0.0.0.0","config-path":"./test/test.yaml","db-address":"127.0.0.1","db-database":"postgres","db-password":"postgres","db-port":5432,"db-tls-ca-cert":"","db-tls-mode":"disable","db-type":"postgres","db-user":"postgres","help":false,"host":"gts.example.org","letsencrypt-cert-dir":"/gotosocial/storage/certs","letsencrypt-email-address":"","letsencrypt-enabled":true,"letsencrypt-port":80,"log-level":"info","media-description-max-chars":500,"media-description-min-chars":0,"media-image-max-size":2097152,"media-video-max-size":10485760,"oidc-client-id":"","oidc-client-secret":"","oidc-enabled":false,"oidc-idp-name":"","oidc-issuer":"","oidc-scopes":["openid","email","profile","groups"],"oidc-skip-verification":false,"port":8080,"protocol":"https","smtp-from":"someone@example.org","smtp-host":"verycoolemailhost.mail","smtp-password":"smtp-password","smtp-port":8888,"smtp-username":"smtp-username","software-version":"","statuses-cw-max-chars":100,"statuses-max-chars":5000,"statuses-media-max-files":6,"statuses-poll-max-options":6,"statuses-poll-option-max-chars":50,"storage-backend":"local","storage-local-base-path":"/gotosocial/storage","syslog-address":"localhost:514","syslog-enabled":false,"syslog-protocol":"udp","trusted-proxies":["127.0.0.1/32","0.0.0.0/0"],"web-asset-base-dir":"./web/assets/","web-template-base-dir":"./web/template/"}'  TEST_5="$(GTS_CONFIG_PATH=./test/test.yaml go run ./cmd/gotosocial/... debug config)"  if [ "${TEST_5}" != "${TEST_5_EXPECTED}" ]; then      echo "TEST_5 not equal TEST_5_EXPECTED" @@ -55,7 +55,7 @@ else  fi  echo "TEST_6 Test loading a config file by passing cli flag." -TEST_6_EXPECTED='{"account-domain":"example.org","accounts-approval-required":true,"accounts-reason-required":true,"accounts-registration-open":true,"application-name":"gotosocial","bind-address":"0.0.0.0","config-path":"./test/test.yaml","db-address":"127.0.0.1","db-database":"postgres","db-password":"postgres","db-port":5432,"db-tls-ca-cert":"","db-tls-mode":"disable","db-type":"postgres","db-user":"postgres","help":false,"host":"gts.example.org","letsencrypt-cert-dir":"/gotosocial/storage/certs","letsencrypt-email-address":"","letsencrypt-enabled":true,"letsencrypt-port":80,"log-level":"info","media-description-max-chars":500,"media-description-min-chars":0,"media-image-max-size":2097152,"media-video-max-size":10485760,"oidc-client-id":"","oidc-client-secret":"","oidc-enabled":false,"oidc-idp-name":"","oidc-issuer":"","oidc-scopes":["openid","email","profile","groups"],"oidc-skip-verification":false,"port":8080,"protocol":"https","smtp-from":"someone@example.org","smtp-host":"verycoolemailhost.mail","smtp-password":"smtp-password","smtp-port":8888,"smtp-username":"smtp-username","software-version":"","statuses-cw-max-chars":100,"statuses-max-chars":5000,"statuses-media-max-files":6,"statuses-poll-max-options":6,"statuses-poll-option-max-chars":50,"storage-backend":"local","storage-base-path":"/gotosocial/storage","storage-serve-base-path":"/fileserver","storage-serve-host":"localhost","storage-serve-protocol":"https","syslog-address":"localhost:514","syslog-enabled":false,"syslog-protocol":"udp","trusted-proxies":["127.0.0.1/32","0.0.0.0/0"],"web-asset-base-dir":"./web/assets/","web-template-base-dir":"./web/template/"}' +TEST_6_EXPECTED='{"account-domain":"example.org","accounts-approval-required":true,"accounts-reason-required":true,"accounts-registration-open":true,"application-name":"gotosocial","bind-address":"0.0.0.0","config-path":"./test/test.yaml","db-address":"127.0.0.1","db-database":"postgres","db-password":"postgres","db-port":5432,"db-tls-ca-cert":"","db-tls-mode":"disable","db-type":"postgres","db-user":"postgres","help":false,"host":"gts.example.org","letsencrypt-cert-dir":"/gotosocial/storage/certs","letsencrypt-email-address":"","letsencrypt-enabled":true,"letsencrypt-port":80,"log-level":"info","media-description-max-chars":500,"media-description-min-chars":0,"media-image-max-size":2097152,"media-video-max-size":10485760,"oidc-client-id":"","oidc-client-secret":"","oidc-enabled":false,"oidc-idp-name":"","oidc-issuer":"","oidc-scopes":["openid","email","profile","groups"],"oidc-skip-verification":false,"port":8080,"protocol":"https","smtp-from":"someone@example.org","smtp-host":"verycoolemailhost.mail","smtp-password":"smtp-password","smtp-port":8888,"smtp-username":"smtp-username","software-version":"","statuses-cw-max-chars":100,"statuses-max-chars":5000,"statuses-media-max-files":6,"statuses-poll-max-options":6,"statuses-poll-option-max-chars":50,"storage-backend":"local","storage-local-base-path":"/gotosocial/storage","syslog-address":"localhost:514","syslog-enabled":false,"syslog-protocol":"udp","trusted-proxies":["127.0.0.1/32","0.0.0.0/0"],"web-asset-base-dir":"./web/assets/","web-template-base-dir":"./web/template/"}'  TEST_6="$(go run ./cmd/gotosocial/... --config-path ./test/test.yaml debug config)"  if [ "${TEST_6}" != "${TEST_6_EXPECTED}" ]; then      echo "TEST_6 not equal TEST_6_EXPECTED" @@ -65,7 +65,7 @@ else  fi  echo "TEST_7 Test loading a config file and overriding one of the variables with a cli flag." -TEST_7_EXPECTED='{"account-domain":"","accounts-approval-required":true,"accounts-reason-required":true,"accounts-registration-open":true,"application-name":"gotosocial","bind-address":"0.0.0.0","config-path":"./test/test.yaml","db-address":"127.0.0.1","db-database":"postgres","db-password":"postgres","db-port":5432,"db-tls-ca-cert":"","db-tls-mode":"disable","db-type":"postgres","db-user":"postgres","help":false,"host":"gts.example.org","letsencrypt-cert-dir":"/gotosocial/storage/certs","letsencrypt-email-address":"","letsencrypt-enabled":true,"letsencrypt-port":80,"log-level":"info","media-description-max-chars":500,"media-description-min-chars":0,"media-image-max-size":2097152,"media-video-max-size":10485760,"oidc-client-id":"","oidc-client-secret":"","oidc-enabled":false,"oidc-idp-name":"","oidc-issuer":"","oidc-scopes":["openid","email","profile","groups"],"oidc-skip-verification":false,"port":8080,"protocol":"https","smtp-from":"someone@example.org","smtp-host":"verycoolemailhost.mail","smtp-password":"smtp-password","smtp-port":8888,"smtp-username":"smtp-username","software-version":"","statuses-cw-max-chars":100,"statuses-max-chars":5000,"statuses-media-max-files":6,"statuses-poll-max-options":6,"statuses-poll-option-max-chars":50,"storage-backend":"local","storage-base-path":"/gotosocial/storage","storage-serve-base-path":"/fileserver","storage-serve-host":"localhost","storage-serve-protocol":"https","syslog-address":"localhost:514","syslog-enabled":false,"syslog-protocol":"udp","trusted-proxies":["127.0.0.1/32","0.0.0.0/0"],"web-asset-base-dir":"./web/assets/","web-template-base-dir":"./web/template/"}' +TEST_7_EXPECTED='{"account-domain":"","accounts-approval-required":true,"accounts-reason-required":true,"accounts-registration-open":true,"application-name":"gotosocial","bind-address":"0.0.0.0","config-path":"./test/test.yaml","db-address":"127.0.0.1","db-database":"postgres","db-password":"postgres","db-port":5432,"db-tls-ca-cert":"","db-tls-mode":"disable","db-type":"postgres","db-user":"postgres","help":false,"host":"gts.example.org","letsencrypt-cert-dir":"/gotosocial/storage/certs","letsencrypt-email-address":"","letsencrypt-enabled":true,"letsencrypt-port":80,"log-level":"info","media-description-max-chars":500,"media-description-min-chars":0,"media-image-max-size":2097152,"media-video-max-size":10485760,"oidc-client-id":"","oidc-client-secret":"","oidc-enabled":false,"oidc-idp-name":"","oidc-issuer":"","oidc-scopes":["openid","email","profile","groups"],"oidc-skip-verification":false,"port":8080,"protocol":"https","smtp-from":"someone@example.org","smtp-host":"verycoolemailhost.mail","smtp-password":"smtp-password","smtp-port":8888,"smtp-username":"smtp-username","software-version":"","statuses-cw-max-chars":100,"statuses-max-chars":5000,"statuses-media-max-files":6,"statuses-poll-max-options":6,"statuses-poll-option-max-chars":50,"storage-backend":"local","storage-local-base-path":"/gotosocial/storage","syslog-address":"localhost:514","syslog-enabled":false,"syslog-protocol":"udp","trusted-proxies":["127.0.0.1/32","0.0.0.0/0"],"web-asset-base-dir":"./web/assets/","web-template-base-dir":"./web/template/"}'  TEST_7="$(go run ./cmd/gotosocial/... --config-path ./test/test.yaml --account-domain '' debug config)"  if [ "${TEST_7}" != "${TEST_7_EXPECTED}" ]; then      echo "TEST_7 not equal TEST_7_EXPECTED" @@ -75,7 +75,7 @@ else  fi  echo "TEST_8 Test loading a config file and overriding one of the variables with an env var." -TEST_8_EXPECTED='{"account-domain":"peepee","accounts-approval-required":true,"accounts-reason-required":true,"accounts-registration-open":true,"application-name":"gotosocial","bind-address":"0.0.0.0","config-path":"./test/test.yaml","db-address":"127.0.0.1","db-database":"postgres","db-password":"postgres","db-port":5432,"db-tls-ca-cert":"","db-tls-mode":"disable","db-type":"postgres","db-user":"postgres","help":false,"host":"gts.example.org","letsencrypt-cert-dir":"/gotosocial/storage/certs","letsencrypt-email-address":"","letsencrypt-enabled":true,"letsencrypt-port":80,"log-level":"info","media-description-max-chars":500,"media-description-min-chars":0,"media-image-max-size":2097152,"media-video-max-size":10485760,"oidc-client-id":"","oidc-client-secret":"","oidc-enabled":false,"oidc-idp-name":"","oidc-issuer":"","oidc-scopes":["openid","email","profile","groups"],"oidc-skip-verification":false,"port":8080,"protocol":"https","smtp-from":"someone@example.org","smtp-host":"verycoolemailhost.mail","smtp-password":"smtp-password","smtp-port":8888,"smtp-username":"smtp-username","software-version":"","statuses-cw-max-chars":100,"statuses-max-chars":5000,"statuses-media-max-files":6,"statuses-poll-max-options":6,"statuses-poll-option-max-chars":50,"storage-backend":"local","storage-base-path":"/gotosocial/storage","storage-serve-base-path":"/fileserver","storage-serve-host":"localhost","storage-serve-protocol":"https","syslog-address":"localhost:514","syslog-enabled":false,"syslog-protocol":"udp","trusted-proxies":["127.0.0.1/32","0.0.0.0/0"],"web-asset-base-dir":"./web/assets/","web-template-base-dir":"./web/template/"}' +TEST_8_EXPECTED='{"account-domain":"peepee","accounts-approval-required":true,"accounts-reason-required":true,"accounts-registration-open":true,"application-name":"gotosocial","bind-address":"0.0.0.0","config-path":"./test/test.yaml","db-address":"127.0.0.1","db-database":"postgres","db-password":"postgres","db-port":5432,"db-tls-ca-cert":"","db-tls-mode":"disable","db-type":"postgres","db-user":"postgres","help":false,"host":"gts.example.org","letsencrypt-cert-dir":"/gotosocial/storage/certs","letsencrypt-email-address":"","letsencrypt-enabled":true,"letsencrypt-port":80,"log-level":"info","media-description-max-chars":500,"media-description-min-chars":0,"media-image-max-size":2097152,"media-video-max-size":10485760,"oidc-client-id":"","oidc-client-secret":"","oidc-enabled":false,"oidc-idp-name":"","oidc-issuer":"","oidc-scopes":["openid","email","profile","groups"],"oidc-skip-verification":false,"port":8080,"protocol":"https","smtp-from":"someone@example.org","smtp-host":"verycoolemailhost.mail","smtp-password":"smtp-password","smtp-port":8888,"smtp-username":"smtp-username","software-version":"","statuses-cw-max-chars":100,"statuses-max-chars":5000,"statuses-media-max-files":6,"statuses-poll-max-options":6,"statuses-poll-option-max-chars":50,"storage-backend":"local","storage-local-base-path":"/gotosocial/storage","syslog-address":"localhost:514","syslog-enabled":false,"syslog-protocol":"udp","trusted-proxies":["127.0.0.1/32","0.0.0.0/0"],"web-asset-base-dir":"./web/assets/","web-template-base-dir":"./web/template/"}'  TEST_8="$(GTS_ACCOUNT_DOMAIN='peepee' go run ./cmd/gotosocial/... --config-path ./test/test.yaml debug config)"  if [ "${TEST_8}" != "${TEST_8_EXPECTED}" ]; then      echo "TEST_8 not equal TEST_8_EXPECTED" @@ -85,7 +85,7 @@ else  fi  echo "TEST_9 Test loading a config file and overriding one of the variables with both an env var and a cli flag. The cli flag should have priority." -TEST_9_EXPECTED='{"account-domain":"","accounts-approval-required":true,"accounts-reason-required":true,"accounts-registration-open":true,"application-name":"gotosocial","bind-address":"0.0.0.0","config-path":"./test/test.yaml","db-address":"127.0.0.1","db-database":"postgres","db-password":"postgres","db-port":5432,"db-tls-ca-cert":"","db-tls-mode":"disable","db-type":"postgres","db-user":"postgres","help":false,"host":"gts.example.org","letsencrypt-cert-dir":"/gotosocial/storage/certs","letsencrypt-email-address":"","letsencrypt-enabled":true,"letsencrypt-port":80,"log-level":"info","media-description-max-chars":500,"media-description-min-chars":0,"media-image-max-size":2097152,"media-video-max-size":10485760,"oidc-client-id":"","oidc-client-secret":"","oidc-enabled":false,"oidc-idp-name":"","oidc-issuer":"","oidc-scopes":["openid","email","profile","groups"],"oidc-skip-verification":false,"port":8080,"protocol":"https","smtp-from":"someone@example.org","smtp-host":"verycoolemailhost.mail","smtp-password":"smtp-password","smtp-port":8888,"smtp-username":"smtp-username","software-version":"","statuses-cw-max-chars":100,"statuses-max-chars":5000,"statuses-media-max-files":6,"statuses-poll-max-options":6,"statuses-poll-option-max-chars":50,"storage-backend":"local","storage-base-path":"/gotosocial/storage","storage-serve-base-path":"/fileserver","storage-serve-host":"localhost","storage-serve-protocol":"https","syslog-address":"localhost:514","syslog-enabled":false,"syslog-protocol":"udp","trusted-proxies":["127.0.0.1/32","0.0.0.0/0"],"web-asset-base-dir":"./web/assets/","web-template-base-dir":"./web/template/"}' +TEST_9_EXPECTED='{"account-domain":"","accounts-approval-required":true,"accounts-reason-required":true,"accounts-registration-open":true,"application-name":"gotosocial","bind-address":"0.0.0.0","config-path":"./test/test.yaml","db-address":"127.0.0.1","db-database":"postgres","db-password":"postgres","db-port":5432,"db-tls-ca-cert":"","db-tls-mode":"disable","db-type":"postgres","db-user":"postgres","help":false,"host":"gts.example.org","letsencrypt-cert-dir":"/gotosocial/storage/certs","letsencrypt-email-address":"","letsencrypt-enabled":true,"letsencrypt-port":80,"log-level":"info","media-description-max-chars":500,"media-description-min-chars":0,"media-image-max-size":2097152,"media-video-max-size":10485760,"oidc-client-id":"","oidc-client-secret":"","oidc-enabled":false,"oidc-idp-name":"","oidc-issuer":"","oidc-scopes":["openid","email","profile","groups"],"oidc-skip-verification":false,"port":8080,"protocol":"https","smtp-from":"someone@example.org","smtp-host":"verycoolemailhost.mail","smtp-password":"smtp-password","smtp-port":8888,"smtp-username":"smtp-username","software-version":"","statuses-cw-max-chars":100,"statuses-max-chars":5000,"statuses-media-max-files":6,"statuses-poll-max-options":6,"statuses-poll-option-max-chars":50,"storage-backend":"local","storage-local-base-path":"/gotosocial/storage","syslog-address":"localhost:514","syslog-enabled":false,"syslog-protocol":"udp","trusted-proxies":["127.0.0.1/32","0.0.0.0/0"],"web-asset-base-dir":"./web/assets/","web-template-base-dir":"./web/template/"}'  TEST_9="$(GTS_ACCOUNT_DOMAIN='peepee' go run ./cmd/gotosocial/... --config-path ./test/test.yaml --account-domain '' debug config)"  if [ "${TEST_9}" != "${TEST_9_EXPECTED}" ]; then      echo "TEST_9 not equal TEST_9_EXPECTED" @@ -95,7 +95,7 @@ else  fi  echo "TEST_10 Test loading a config file from json." -TEST_10_EXPECTED='{"account-domain":"example.org","accounts-approval-required":true,"accounts-reason-required":true,"accounts-registration-open":true,"application-name":"gotosocial","bind-address":"0.0.0.0","config-path":"./test/test.json","db-address":"127.0.0.1","db-database":"postgres","db-password":"postgres","db-port":5432,"db-tls-ca-cert":"","db-tls-mode":"disable","db-type":"postgres","db-user":"postgres","help":false,"host":"gts.example.org","letsencrypt-cert-dir":"/gotosocial/storage/certs","letsencrypt-email-address":"","letsencrypt-enabled":true,"letsencrypt-port":80,"log-level":"info","media-description-max-chars":500,"media-description-min-chars":0,"media-image-max-size":2097152,"media-video-max-size":10485760,"oidc-client-id":"","oidc-client-secret":"","oidc-enabled":false,"oidc-idp-name":"","oidc-issuer":"","oidc-scopes":["openid","email","profile","groups"],"oidc-skip-verification":false,"port":8080,"protocol":"https","smtp-from":"someone@example.org","smtp-host":"verycoolemailhost.mail","smtp-password":"smtp-password","smtp-port":8888,"smtp-username":"smtp-username","software-version":"","statuses-cw-max-chars":100,"statuses-max-chars":5000,"statuses-media-max-files":6,"statuses-poll-max-options":6,"statuses-poll-option-max-chars":50,"storage-backend":"local","storage-base-path":"/gotosocial/storage","storage-serve-base-path":"/fileserver","storage-serve-host":"localhost","storage-serve-protocol":"https","syslog-address":"localhost:514","syslog-enabled":false,"syslog-protocol":"udp","trusted-proxies":["127.0.0.1/32","0.0.0.0/0"],"web-asset-base-dir":"./web/assets/","web-template-base-dir":"./web/template/"}' +TEST_10_EXPECTED='{"account-domain":"example.org","accounts-approval-required":true,"accounts-reason-required":true,"accounts-registration-open":true,"application-name":"gotosocial","bind-address":"0.0.0.0","config-path":"./test/test.json","db-address":"127.0.0.1","db-database":"postgres","db-password":"postgres","db-port":5432,"db-tls-ca-cert":"","db-tls-mode":"disable","db-type":"postgres","db-user":"postgres","help":false,"host":"gts.example.org","letsencrypt-cert-dir":"/gotosocial/storage/certs","letsencrypt-email-address":"","letsencrypt-enabled":true,"letsencrypt-port":80,"log-level":"info","media-description-max-chars":500,"media-description-min-chars":0,"media-image-max-size":2097152,"media-video-max-size":10485760,"oidc-client-id":"","oidc-client-secret":"","oidc-enabled":false,"oidc-idp-name":"","oidc-issuer":"","oidc-scopes":["openid","email","profile","groups"],"oidc-skip-verification":false,"port":8080,"protocol":"https","smtp-from":"someone@example.org","smtp-host":"verycoolemailhost.mail","smtp-password":"smtp-password","smtp-port":8888,"smtp-username":"smtp-username","software-version":"","statuses-cw-max-chars":100,"statuses-max-chars":5000,"statuses-media-max-files":6,"statuses-poll-max-options":6,"statuses-poll-option-max-chars":50,"storage-backend":"local","storage-local-base-path":"/gotosocial/storage","syslog-address":"localhost:514","syslog-enabled":false,"syslog-protocol":"udp","trusted-proxies":["127.0.0.1/32","0.0.0.0/0"],"web-asset-base-dir":"./web/assets/","web-template-base-dir":"./web/template/"}'  TEST_10="$(go run ./cmd/gotosocial/... --config-path ./test/test.json debug config)"  if [ "${TEST_10}" != "${TEST_10_EXPECTED}" ]; then      echo "TEST_10 not equal TEST_10_EXPECTED" @@ -105,7 +105,7 @@ else  fi  echo "TEST_11 Test loading a partial config file. Default values should be used apart from those set in the config file." -TEST_11_EXPECTED='{"account-domain":"peepee.poopoo","accounts-approval-required":true,"accounts-reason-required":true,"accounts-registration-open":true,"application-name":"gotosocial","bind-address":"0.0.0.0","config-path":"./test/test2.yaml","db-address":"localhost","db-database":"postgres","db-password":"postgres","db-port":5432,"db-tls-ca-cert":"","db-tls-mode":"disable","db-type":"postgres","db-user":"postgres","help":false,"host":"","letsencrypt-cert-dir":"/gotosocial/storage/certs","letsencrypt-email-address":"","letsencrypt-enabled":true,"letsencrypt-port":80,"log-level":"trace","media-description-max-chars":500,"media-description-min-chars":0,"media-image-max-size":2097152,"media-video-max-size":10485760,"oidc-client-id":"","oidc-client-secret":"","oidc-enabled":false,"oidc-idp-name":"","oidc-issuer":"","oidc-scopes":["openid","profile","email","groups"],"oidc-skip-verification":false,"port":8080,"protocol":"https","smtp-from":"GoToSocial","smtp-host":"","smtp-password":"","smtp-port":0,"smtp-username":"","software-version":"","statuses-cw-max-chars":100,"statuses-max-chars":5000,"statuses-media-max-files":6,"statuses-poll-max-options":6,"statuses-poll-option-max-chars":50,"storage-backend":"local","storage-base-path":"/gotosocial/storage","storage-serve-base-path":"/fileserver","storage-serve-host":"localhost","storage-serve-protocol":"https","syslog-address":"localhost:514","syslog-enabled":false,"syslog-protocol":"udp","trusted-proxies":["127.0.0.1/32"],"web-asset-base-dir":"./web/assets/","web-template-base-dir":"./web/template/"}' +TEST_11_EXPECTED='{"account-domain":"peepee.poopoo","accounts-approval-required":true,"accounts-reason-required":true,"accounts-registration-open":true,"application-name":"gotosocial","bind-address":"0.0.0.0","config-path":"./test/test2.yaml","db-address":"localhost","db-database":"postgres","db-password":"postgres","db-port":5432,"db-tls-ca-cert":"","db-tls-mode":"disable","db-type":"postgres","db-user":"postgres","help":false,"host":"","letsencrypt-cert-dir":"/gotosocial/storage/certs","letsencrypt-email-address":"","letsencrypt-enabled":true,"letsencrypt-port":80,"log-level":"trace","media-description-max-chars":500,"media-description-min-chars":0,"media-image-max-size":2097152,"media-video-max-size":10485760,"oidc-client-id":"","oidc-client-secret":"","oidc-enabled":false,"oidc-idp-name":"","oidc-issuer":"","oidc-scopes":["openid","profile","email","groups"],"oidc-skip-verification":false,"port":8080,"protocol":"https","smtp-from":"GoToSocial","smtp-host":"","smtp-password":"","smtp-port":0,"smtp-username":"","software-version":"","statuses-cw-max-chars":100,"statuses-max-chars":5000,"statuses-media-max-files":6,"statuses-poll-max-options":6,"statuses-poll-option-max-chars":50,"storage-backend":"local","storage-local-base-path":"/gotosocial/storage","syslog-address":"localhost:514","syslog-enabled":false,"syslog-protocol":"udp","trusted-proxies":["127.0.0.1/32"],"web-asset-base-dir":"./web/assets/","web-template-base-dir":"./web/template/"}'  TEST_11="$(go run ./cmd/gotosocial/... --config-path ./test/test2.yaml debug config)"  if [ "${TEST_11}" != "${TEST_11_EXPECTED}" ]; then      echo "TEST_11 not equal TEST_11_EXPECTED" diff --git a/test/test.json b/test/test.json index 3d0387ea2..d12b06d50 100644 --- a/test/test.json +++ b/test/test.json @@ -51,10 +51,7 @@      "statuses-poll-max-options": 6,      "statuses-poll-option-max-chars": 50,      "storage-backend": "local", -    "storage-base-path": "/gotosocial/storage", -    "storage-serve-base-path": "/fileserver", -    "storage-serve-host": "localhost", -    "storage-serve-protocol": "https", +    "storage-local-base-path": "/gotosocial/storage",      "trusted-proxies": [          "127.0.0.1/32",          "0.0.0.0/0" diff --git a/test/test.yaml b/test/test.yaml index 96e53a747..a3d82744e 100644 --- a/test/test.yaml +++ b/test/test.yaml @@ -214,27 +214,7 @@ storage-backend: "local"  # this directly, and create new subdirectories and files with in.  # Examples: ["/home/gotosocial/storage", "/opt/gotosocial/datastorage"]  # Default: "/gotosocial/storage" -storage-base-path: "/gotosocial/storage" - -# String. Protocol to use for serving stored files. -# It's very unlikely that you'll need to change this ever, but there might be edge cases. -# Examples: ["http", "https"] -storage-serve-protocol: "https" - -# String. Host for serving stored files. -# If you're using local storage, this should be THE SAME as the value you've set for Host, above. -# It should only be a different value if you're serving stored files from a host -# other than the one your instance is running on. -# Examples: ["localhost", "example.org"] -# Default: "localhost" -- you should absolutely change this. -storage-serve-host: "localhost" - -# String. Base path for serving stored files. This will be added to serveHost and serveProtocol -# to form the prefix url of your stored files. Eg., https://example.org/fileserver/..... -# It's unlikely that you will need to change this. -# Examples: ["/fileserver", "/media"] -# Default: "/fileserver" -storage-serve-base-path: "/fileserver" +storage-local-base-path: "/gotosocial/storage"  ###########################  ##### STATUSES CONFIG ##### diff --git a/testrig/config.go b/testrig/config.go index 3857ddb34..f9b1e0bcf 100644 --- a/testrig/config.go +++ b/testrig/config.go @@ -88,10 +88,7 @@ var TestDefaults = config.Values{  	MediaDescriptionMaxChars: 500,  	StorageBackend:       "local", -	StorageBasePath:      "/gotosocial/storage", -	StorageServeProtocol: "http", -	StorageServeHost:     "localhost:8080", -	StorageServeBasePath: "/fileserver", +	StorageLocalBasePath: "/gotosocial/storage",  	StatusesMaxChars:           5000,  	StatusesCWMaxChars:         100,  | 
