diff options
Diffstat (limited to 'internal/apimodule/account')
-rw-r--r-- | internal/apimodule/account/account.go | 47 | ||||
-rw-r--r-- | internal/apimodule/account/accountcreate.go | 6 | ||||
-rw-r--r-- | internal/apimodule/account/accountget.go | 6 | ||||
-rw-r--r-- | internal/apimodule/account/accountupdate.go | 8 | ||||
-rw-r--r-- | internal/apimodule/account/accountverify.go | 4 | ||||
-rw-r--r-- | internal/apimodule/account/test/accountcreate_test.go (renamed from internal/apimodule/account/accountcreate_test.go) | 43 | ||||
-rw-r--r-- | internal/apimodule/account/test/accountupdate_test.go (renamed from internal/apimodule/account/accountupdate_test.go) | 11 | ||||
-rw-r--r-- | internal/apimodule/account/test/accountverify_test.go (renamed from internal/apimodule/account/accountverify_test.go) | 0 |
8 files changed, 67 insertions, 58 deletions
diff --git a/internal/apimodule/account/account.go b/internal/apimodule/account/account.go index f4a47f6a2..a836afcdb 100644 --- a/internal/apimodule/account/account.go +++ b/internal/apimodule/account/account.go @@ -37,25 +37,31 @@ import ( ) const ( - idKey = "id" - basePath = "/api/v1/accounts" - basePathWithID = basePath + "/:" + idKey - verifyPath = basePath + "/verify_credentials" - updateCredentialsPath = basePath + "/update_credentials" + // IDKey is the key to use for retrieving account ID in requests + IDKey = "id" + // BasePath is the base API path for this module + BasePath = "/api/v1/accounts" + // BasePathWithID is the base path for this module with the ID key + BasePathWithID = BasePath + "/:" + IDKey + // VerifyPath is for verifying account credentials + VerifyPath = BasePath + "/verify_credentials" + // UpdateCredentialsPath is for updating account credentials + UpdateCredentialsPath = BasePath + "/update_credentials" ) -type accountModule struct { +// Module implements the ClientAPIModule interface for account-related actions +type Module struct { config *config.Config db db.DB oauthServer oauth.Server - mediaHandler media.MediaHandler + mediaHandler media.Handler mastoConverter mastotypes.Converter log *logrus.Logger } // New returns a new account module -func New(config *config.Config, db db.DB, oauthServer oauth.Server, mediaHandler media.MediaHandler, mastoConverter mastotypes.Converter, log *logrus.Logger) apimodule.ClientAPIModule { - return &accountModule{ +func New(config *config.Config, db db.DB, oauthServer oauth.Server, mediaHandler media.Handler, mastoConverter mastotypes.Converter, log *logrus.Logger) apimodule.ClientAPIModule { + return &Module{ config: config, db: db, oauthServer: oauthServer, @@ -66,14 +72,15 @@ func New(config *config.Config, db db.DB, oauthServer oauth.Server, mediaHandler } // Route attaches all routes from this module to the given router -func (m *accountModule) Route(r router.Router) error { - r.AttachHandler(http.MethodPost, basePath, m.accountCreatePOSTHandler) - r.AttachHandler(http.MethodGet, basePathWithID, m.muxHandler) - r.AttachHandler(http.MethodPatch, basePathWithID, m.muxHandler) +func (m *Module) Route(r router.Router) error { + r.AttachHandler(http.MethodPost, BasePath, m.AccountCreatePOSTHandler) + r.AttachHandler(http.MethodGet, BasePathWithID, m.muxHandler) + r.AttachHandler(http.MethodPatch, BasePathWithID, m.muxHandler) return nil } -func (m *accountModule) CreateTables(db db.DB) error { +// CreateTables creates the required tables for this module in the given database +func (m *Module) CreateTables(db db.DB) error { models := []interface{}{ >smodel.User{}, >smodel.Account{}, @@ -93,18 +100,18 @@ func (m *accountModule) CreateTables(db db.DB) error { return nil } -func (m *accountModule) muxHandler(c *gin.Context) { +func (m *Module) muxHandler(c *gin.Context) { ru := c.Request.RequestURI switch c.Request.Method { case http.MethodGet: - if strings.HasPrefix(ru, verifyPath) { - m.accountVerifyGETHandler(c) + if strings.HasPrefix(ru, VerifyPath) { + m.AccountVerifyGETHandler(c) } else { - m.accountGETHandler(c) + m.AccountGETHandler(c) } case http.MethodPatch: - if strings.HasPrefix(ru, updateCredentialsPath) { - m.accountUpdateCredentialsPATCHHandler(c) + if strings.HasPrefix(ru, UpdateCredentialsPath) { + m.AccountUpdateCredentialsPATCHHandler(c) } } } diff --git a/internal/apimodule/account/accountcreate.go b/internal/apimodule/account/accountcreate.go index 266d820af..fb21925b8 100644 --- a/internal/apimodule/account/accountcreate.go +++ b/internal/apimodule/account/accountcreate.go @@ -34,10 +34,10 @@ import ( "github.com/superseriousbusiness/oauth2/v4" ) -// accountCreatePOSTHandler handles create account requests, validates them, +// AccountCreatePOSTHandler handles create account requests, validates them, // and puts them in the database if they're valid. // It should be served as a POST at /api/v1/accounts -func (m *accountModule) accountCreatePOSTHandler(c *gin.Context) { +func (m *Module) AccountCreatePOSTHandler(c *gin.Context) { l := m.log.WithField("func", "accountCreatePOSTHandler") authed, err := oauth.MustAuth(c, true, true, false, false) if err != nil { @@ -83,7 +83,7 @@ func (m *accountModule) accountCreatePOSTHandler(c *gin.Context) { // accountCreate does the dirty work of making an account and user in the database. // It then returns a token to the caller, for use with the new account, as per the // spec here: https://docs.joinmastodon.org/methods/accounts/ -func (m *accountModule) accountCreate(form *mastotypes.AccountCreateRequest, signUpIP net.IP, token oauth2.TokenInfo, app *gtsmodel.Application) (*mastotypes.Token, error) { +func (m *Module) accountCreate(form *mastotypes.AccountCreateRequest, signUpIP net.IP, token oauth2.TokenInfo, app *gtsmodel.Application) (*mastotypes.Token, error) { l := m.log.WithField("func", "accountCreate") // don't store a reason if we don't require one diff --git a/internal/apimodule/account/accountget.go b/internal/apimodule/account/accountget.go index cd4aed22e..5003be139 100644 --- a/internal/apimodule/account/accountget.go +++ b/internal/apimodule/account/accountget.go @@ -26,12 +26,12 @@ import ( "github.com/superseriousbusiness/gotosocial/internal/db/gtsmodel" ) -// accountGetHandler serves the account information held by the server in response to a GET +// AccountGETHandler serves the account information held by the server in response to a GET // request. It should be served as a GET at /api/v1/accounts/:id. // // See: https://docs.joinmastodon.org/methods/accounts/ -func (m *accountModule) accountGETHandler(c *gin.Context) { - targetAcctID := c.Param(idKey) +func (m *Module) AccountGETHandler(c *gin.Context) { + targetAcctID := c.Param(IDKey) if targetAcctID == "" { c.JSON(http.StatusBadRequest, gin.H{"error": "no account id specified"}) return diff --git a/internal/apimodule/account/accountupdate.go b/internal/apimodule/account/accountupdate.go index 15e9cf0d1..7709697bf 100644 --- a/internal/apimodule/account/accountupdate.go +++ b/internal/apimodule/account/accountupdate.go @@ -34,7 +34,7 @@ import ( "github.com/superseriousbusiness/gotosocial/internal/util" ) -// accountUpdateCredentialsPATCHHandler allows a user to modify their account/profile settings. +// AccountUpdateCredentialsPATCHHandler allows a user to modify their account/profile settings. // It should be served as a PATCH at /api/v1/accounts/update_credentials // // TODO: this can be optimized massively by building up a picture of what we want the new account @@ -42,7 +42,7 @@ import ( // which is not gonna make the database very happy when lots of requests are going through. // This way it would also be safer because the update won't happen until *all* the fields are validated. // Otherwise we risk doing a partial update and that's gonna cause probllleeemmmsss. -func (m *accountModule) accountUpdateCredentialsPATCHHandler(c *gin.Context) { +func (m *Module) AccountUpdateCredentialsPATCHHandler(c *gin.Context) { l := m.log.WithField("func", "accountUpdateCredentialsPATCHHandler") authed, err := oauth.MustAuth(c, true, false, false, true) if err != nil { @@ -196,7 +196,7 @@ func (m *accountModule) accountUpdateCredentialsPATCHHandler(c *gin.Context) { // UpdateAccountAvatar does the dirty work of checking the avatar part of an account update form, // parsing and checking the image, and doing the necessary updates in the database for this to become // the account's new avatar image. -func (m *accountModule) UpdateAccountAvatar(avatar *multipart.FileHeader, accountID string) (*gtsmodel.MediaAttachment, error) { +func (m *Module) UpdateAccountAvatar(avatar *multipart.FileHeader, accountID string) (*gtsmodel.MediaAttachment, error) { var err error if int(avatar.Size) > m.config.MediaConfig.MaxImageSize { err = fmt.Errorf("avatar with size %d exceeded max image size of %d bytes", avatar.Size, m.config.MediaConfig.MaxImageSize) @@ -229,7 +229,7 @@ func (m *accountModule) UpdateAccountAvatar(avatar *multipart.FileHeader, accoun // UpdateAccountHeader does the dirty work of checking the header part of an account update form, // parsing and checking the image, and doing the necessary updates in the database for this to become // the account's new header image. -func (m *accountModule) UpdateAccountHeader(header *multipart.FileHeader, accountID string) (*gtsmodel.MediaAttachment, error) { +func (m *Module) UpdateAccountHeader(header *multipart.FileHeader, accountID string) (*gtsmodel.MediaAttachment, error) { var err error if int(header.Size) > m.config.MediaConfig.MaxImageSize { err = fmt.Errorf("header with size %d exceeded max image size of %d bytes", header.Size, m.config.MediaConfig.MaxImageSize) diff --git a/internal/apimodule/account/accountverify.go b/internal/apimodule/account/accountverify.go index 584ab6122..9edf1e73a 100644 --- a/internal/apimodule/account/accountverify.go +++ b/internal/apimodule/account/accountverify.go @@ -25,10 +25,10 @@ import ( "github.com/superseriousbusiness/gotosocial/internal/oauth" ) -// accountVerifyGETHandler serves a user's account details to them IF they reached this +// AccountVerifyGETHandler serves a user's account details to them IF they reached this // handler while in possession of a valid token, according to the oauth middleware. // It should be served as a GET at /api/v1/accounts/verify_credentials -func (m *accountModule) accountVerifyGETHandler(c *gin.Context) { +func (m *Module) AccountVerifyGETHandler(c *gin.Context) { l := m.log.WithField("func", "accountVerifyGETHandler") authed, err := oauth.MustAuth(c, true, false, false, true) if err != nil { diff --git a/internal/apimodule/account/accountcreate_test.go b/internal/apimodule/account/test/accountcreate_test.go index 8677e3573..81eab467a 100644 --- a/internal/apimodule/account/accountcreate_test.go +++ b/internal/apimodule/account/test/accountcreate_test.go @@ -39,6 +39,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/suite" + "github.com/superseriousbusiness/gotosocial/internal/apimodule/account" "github.com/superseriousbusiness/gotosocial/internal/config" "github.com/superseriousbusiness/gotosocial/internal/db" "github.com/superseriousbusiness/gotosocial/internal/db/gtsmodel" @@ -63,10 +64,10 @@ type AccountCreateTestSuite struct { testToken oauth2.TokenInfo mockOauthServer *oauth.MockServer mockStorage *storage.MockStorage - mediaHandler media.MediaHandler + mediaHandler media.Handler mastoConverter mastotypes.Converter db db.DB - accountModule *accountModule + accountModule *account.Module newUserFormHappyPath url.Values } @@ -164,7 +165,7 @@ func (suite *AccountCreateTestSuite) SetupSuite() { suite.mastoConverter = mastotypes.New(suite.config, suite.db) // and finally here's the thing we're actually testing! - suite.accountModule = New(suite.config, suite.db, suite.mockOauthServer, suite.mediaHandler, suite.mastoConverter, suite.log).(*accountModule) + suite.accountModule = account.New(suite.config, suite.db, suite.mockOauthServer, suite.mediaHandler, suite.mastoConverter, suite.log).(*account.Module) } func (suite *AccountCreateTestSuite) TearDownSuite() { @@ -250,9 +251,9 @@ func (suite *AccountCreateTestSuite) TestAccountCreatePOSTHandlerSuccessful() { ctx, _ := gin.CreateTestContext(recorder) ctx.Set(oauth.SessionAuthorizedApplication, suite.testApplication) ctx.Set(oauth.SessionAuthorizedToken, suite.testToken) - ctx.Request = httptest.NewRequest(http.MethodPost, fmt.Sprintf("http://localhost:8080/%s", basePath), nil) // the endpoint we're hitting + ctx.Request = httptest.NewRequest(http.MethodPost, fmt.Sprintf("http://localhost:8080/%s", account.BasePath), nil) // the endpoint we're hitting ctx.Request.Form = suite.newUserFormHappyPath - suite.accountModule.accountCreatePOSTHandler(ctx) + suite.accountModule.AccountCreatePOSTHandler(ctx) // check response @@ -324,9 +325,9 @@ func (suite *AccountCreateTestSuite) TestAccountCreatePOSTHandlerNoAuth() { // setup recorder := httptest.NewRecorder() ctx, _ := gin.CreateTestContext(recorder) - ctx.Request = httptest.NewRequest(http.MethodPost, fmt.Sprintf("http://localhost:8080/%s", basePath), nil) // the endpoint we're hitting + ctx.Request = httptest.NewRequest(http.MethodPost, fmt.Sprintf("http://localhost:8080/%s", account.BasePath), nil) // the endpoint we're hitting ctx.Request.Form = suite.newUserFormHappyPath - suite.accountModule.accountCreatePOSTHandler(ctx) + suite.accountModule.AccountCreatePOSTHandler(ctx) // check response @@ -349,8 +350,8 @@ func (suite *AccountCreateTestSuite) TestAccountCreatePOSTHandlerNoForm() { ctx, _ := gin.CreateTestContext(recorder) ctx.Set(oauth.SessionAuthorizedApplication, suite.testApplication) ctx.Set(oauth.SessionAuthorizedToken, suite.testToken) - ctx.Request = httptest.NewRequest(http.MethodPost, fmt.Sprintf("http://localhost:8080/%s", basePath), nil) // the endpoint we're hitting - suite.accountModule.accountCreatePOSTHandler(ctx) + ctx.Request = httptest.NewRequest(http.MethodPost, fmt.Sprintf("http://localhost:8080/%s", account.BasePath), nil) // the endpoint we're hitting + suite.accountModule.AccountCreatePOSTHandler(ctx) // check response suite.EqualValues(http.StatusBadRequest, recorder.Code) @@ -371,11 +372,11 @@ func (suite *AccountCreateTestSuite) TestAccountCreatePOSTHandlerWeakPassword() ctx, _ := gin.CreateTestContext(recorder) ctx.Set(oauth.SessionAuthorizedApplication, suite.testApplication) ctx.Set(oauth.SessionAuthorizedToken, suite.testToken) - ctx.Request = httptest.NewRequest(http.MethodPost, fmt.Sprintf("http://localhost:8080/%s", basePath), nil) // the endpoint we're hitting + ctx.Request = httptest.NewRequest(http.MethodPost, fmt.Sprintf("http://localhost:8080/%s", account.BasePath), nil) // the endpoint we're hitting ctx.Request.Form = suite.newUserFormHappyPath // set a weak password ctx.Request.Form.Set("password", "weak") - suite.accountModule.accountCreatePOSTHandler(ctx) + suite.accountModule.AccountCreatePOSTHandler(ctx) // check response suite.EqualValues(http.StatusBadRequest, recorder.Code) @@ -396,11 +397,11 @@ func (suite *AccountCreateTestSuite) TestAccountCreatePOSTHandlerWeirdLocale() { ctx, _ := gin.CreateTestContext(recorder) ctx.Set(oauth.SessionAuthorizedApplication, suite.testApplication) ctx.Set(oauth.SessionAuthorizedToken, suite.testToken) - ctx.Request = httptest.NewRequest(http.MethodPost, fmt.Sprintf("http://localhost:8080/%s", basePath), nil) // the endpoint we're hitting + ctx.Request = httptest.NewRequest(http.MethodPost, fmt.Sprintf("http://localhost:8080/%s", account.BasePath), nil) // the endpoint we're hitting ctx.Request.Form = suite.newUserFormHappyPath // set an invalid locale ctx.Request.Form.Set("locale", "neverneverland") - suite.accountModule.accountCreatePOSTHandler(ctx) + suite.accountModule.AccountCreatePOSTHandler(ctx) // check response suite.EqualValues(http.StatusBadRequest, recorder.Code) @@ -421,12 +422,12 @@ func (suite *AccountCreateTestSuite) TestAccountCreatePOSTHandlerRegistrationsCl ctx, _ := gin.CreateTestContext(recorder) ctx.Set(oauth.SessionAuthorizedApplication, suite.testApplication) ctx.Set(oauth.SessionAuthorizedToken, suite.testToken) - ctx.Request = httptest.NewRequest(http.MethodPost, fmt.Sprintf("http://localhost:8080/%s", basePath), nil) // the endpoint we're hitting + ctx.Request = httptest.NewRequest(http.MethodPost, fmt.Sprintf("http://localhost:8080/%s", account.BasePath), nil) // the endpoint we're hitting ctx.Request.Form = suite.newUserFormHappyPath // close registrations suite.config.AccountsConfig.OpenRegistration = false - suite.accountModule.accountCreatePOSTHandler(ctx) + suite.accountModule.AccountCreatePOSTHandler(ctx) // check response suite.EqualValues(http.StatusBadRequest, recorder.Code) @@ -447,13 +448,13 @@ func (suite *AccountCreateTestSuite) TestAccountCreatePOSTHandlerReasonNotProvid ctx, _ := gin.CreateTestContext(recorder) ctx.Set(oauth.SessionAuthorizedApplication, suite.testApplication) ctx.Set(oauth.SessionAuthorizedToken, suite.testToken) - ctx.Request = httptest.NewRequest(http.MethodPost, fmt.Sprintf("http://localhost:8080/%s", basePath), nil) // the endpoint we're hitting + ctx.Request = httptest.NewRequest(http.MethodPost, fmt.Sprintf("http://localhost:8080/%s", account.BasePath), nil) // the endpoint we're hitting ctx.Request.Form = suite.newUserFormHappyPath // remove reason ctx.Request.Form.Set("reason", "") - suite.accountModule.accountCreatePOSTHandler(ctx) + suite.accountModule.AccountCreatePOSTHandler(ctx) // check response suite.EqualValues(http.StatusBadRequest, recorder.Code) @@ -474,13 +475,13 @@ func (suite *AccountCreateTestSuite) TestAccountCreatePOSTHandlerInsufficientRea ctx, _ := gin.CreateTestContext(recorder) ctx.Set(oauth.SessionAuthorizedApplication, suite.testApplication) ctx.Set(oauth.SessionAuthorizedToken, suite.testToken) - ctx.Request = httptest.NewRequest(http.MethodPost, fmt.Sprintf("http://localhost:8080/%s", basePath), nil) // the endpoint we're hitting + ctx.Request = httptest.NewRequest(http.MethodPost, fmt.Sprintf("http://localhost:8080/%s", account.BasePath), nil) // the endpoint we're hitting ctx.Request.Form = suite.newUserFormHappyPath // remove reason ctx.Request.Form.Set("reason", "just cuz") - suite.accountModule.accountCreatePOSTHandler(ctx) + suite.accountModule.AccountCreatePOSTHandler(ctx) // check response suite.EqualValues(http.StatusBadRequest, recorder.Code) @@ -526,9 +527,9 @@ func (suite *AccountCreateTestSuite) TestAccountUpdateCredentialsPATCHHandler() ctx, _ := gin.CreateTestContext(recorder) ctx.Set(oauth.SessionAuthorizedAccount, suite.testAccountLocal) ctx.Set(oauth.SessionAuthorizedToken, suite.testToken) - ctx.Request = httptest.NewRequest(http.MethodPatch, fmt.Sprintf("http://localhost:8080/%s", updateCredentialsPath), body) // the endpoint we're hitting + ctx.Request = httptest.NewRequest(http.MethodPatch, fmt.Sprintf("http://localhost:8080/%s", account.UpdateCredentialsPath), body) // the endpoint we're hitting ctx.Request.Header.Set("Content-Type", writer.FormDataContentType()) - suite.accountModule.accountUpdateCredentialsPATCHHandler(ctx) + suite.accountModule.AccountUpdateCredentialsPATCHHandler(ctx) // check response diff --git a/internal/apimodule/account/accountupdate_test.go b/internal/apimodule/account/test/accountupdate_test.go index 7ca2190d8..1c6f528a1 100644 --- a/internal/apimodule/account/accountupdate_test.go +++ b/internal/apimodule/account/test/accountupdate_test.go @@ -37,6 +37,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/suite" + "github.com/superseriousbusiness/gotosocial/internal/apimodule/account" "github.com/superseriousbusiness/gotosocial/internal/config" "github.com/superseriousbusiness/gotosocial/internal/db" "github.com/superseriousbusiness/gotosocial/internal/db/gtsmodel" @@ -58,10 +59,10 @@ type AccountUpdateTestSuite struct { testToken oauth2.TokenInfo mockOauthServer *oauth.MockServer mockStorage *storage.MockStorage - mediaHandler media.MediaHandler + mediaHandler media.Handler mastoConverter mastotypes.Converter db db.DB - accountModule *accountModule + accountModule *account.Module newUserFormHappyPath url.Values } @@ -159,7 +160,7 @@ func (suite *AccountUpdateTestSuite) SetupSuite() { suite.mastoConverter = mastotypes.New(suite.config, suite.db) // and finally here's the thing we're actually testing! - suite.accountModule = New(suite.config, suite.db, suite.mockOauthServer, suite.mediaHandler, suite.mastoConverter, suite.log).(*accountModule) + suite.accountModule = account.New(suite.config, suite.db, suite.mockOauthServer, suite.mediaHandler, suite.mastoConverter, suite.log).(*account.Module) } func (suite *AccountUpdateTestSuite) TearDownSuite() { @@ -278,9 +279,9 @@ func (suite *AccountUpdateTestSuite) TestAccountUpdateCredentialsPATCHHandler() ctx, _ := gin.CreateTestContext(recorder) ctx.Set(oauth.SessionAuthorizedAccount, suite.testAccountLocal) ctx.Set(oauth.SessionAuthorizedToken, suite.testToken) - ctx.Request = httptest.NewRequest(http.MethodPatch, fmt.Sprintf("http://localhost:8080/%s", updateCredentialsPath), body) // the endpoint we're hitting + ctx.Request = httptest.NewRequest(http.MethodPatch, fmt.Sprintf("http://localhost:8080/%s", account.UpdateCredentialsPath), body) // the endpoint we're hitting ctx.Request.Header.Set("Content-Type", writer.FormDataContentType()) - suite.accountModule.accountUpdateCredentialsPATCHHandler(ctx) + suite.accountModule.AccountUpdateCredentialsPATCHHandler(ctx) // check response diff --git a/internal/apimodule/account/accountverify_test.go b/internal/apimodule/account/test/accountverify_test.go index 223a0c145..223a0c145 100644 --- a/internal/apimodule/account/accountverify_test.go +++ b/internal/apimodule/account/test/accountverify_test.go |