From 7e796b11ee7310ce8b64851146422a5a48d83271 Mon Sep 17 00:00:00 2001 From: tsmethurst Date: Sat, 27 Mar 2021 18:03:02 +0100 Subject: [PATCH] more tests! --- internal/module/account/account_test.go | 193 +++++++++++++++++++++++- 1 file changed, 186 insertions(+), 7 deletions(-) diff --git a/internal/module/account/account_test.go b/internal/module/account/account_test.go index 60dfd5bef..f712797bd 100644 --- a/internal/module/account/account_test.go +++ b/internal/module/account/account_test.go @@ -105,12 +105,6 @@ func (suite *AccountTestSuite) SetupSuite() { Database: "postgres", ApplicationName: "gotosocial", } - // Default accountsconfig - c.AccountsConfig = &config.AccountsConfig{ - OpenRegistration: true, - RequireApproval: true, - ReasonRequired: true, - } suite.config = c // use an actual database for this, because it's just easier than mocking one out @@ -146,6 +140,7 @@ func (suite *AccountTestSuite) TearDownSuite() { // SetupTest creates a db connection and creates necessary tables before each test func (suite *AccountTestSuite) SetupTest() { + // create all the tables we might need in thie suite models := []interface{}{ &model.User{}, &model.Account{}, @@ -154,7 +149,6 @@ func (suite *AccountTestSuite) SetupTest() { &model.Application{}, &model.EmailDomainBlock{}, } - for _, m := range models { if err := suite.db.CreateTable(m); err != nil { logrus.Panicf("db connection error: %s", err) @@ -170,10 +164,19 @@ func (suite *AccountTestSuite) SetupTest() { "agreement": []string{"true"}, "locale": []string{"en"}, } + + // same with accounts config + suite.config.AccountsConfig = &config.AccountsConfig{ + OpenRegistration: true, + RequireApproval: true, + ReasonRequired: true, + } } // TearDownTest drops tables to make sure there's no data in the db func (suite *AccountTestSuite) TearDownTest() { + + // remove all the tables we might have used so it's clear for the next test models := []interface{}{ &model.User{}, &model.Account{}, @@ -271,6 +274,182 @@ func (suite *AccountTestSuite) TestAccountCreatePOSTHandlerSuccessful() { assert.Nil(suite.T(), err) } +// TestAccountCreatePOSTHandlerNoAuth makes sure that the handler fails when no authorization is provided: +// only registered applications can create accounts, and we don't provide one here. +func (suite *AccountTestSuite) 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.Form = suite.newUserFormHappyPath + suite.accountModule.accountCreatePOSTHandler(ctx) + + // check response + + // 1. we should have forbidden from our call to the function because we didn't auth + suite.EqualValues(http.StatusForbidden, recorder.Code) + + // 2. we should have an error message in the result body + result := recorder.Result() + defer result.Body.Close() + b, err := ioutil.ReadAll(result.Body) + assert.NoError(suite.T(), err) + assert.Equal(suite.T(), `{"error":"not authorized"}`, string(b)) +} + +// TestAccountCreatePOSTHandlerNoAuth makes sure that the handler fails when no form is provided at all. +func (suite *AccountTestSuite) TestAccountCreatePOSTHandlerNoForm() { + + // setup + recorder := httptest.NewRecorder() + 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) + + // check response + suite.EqualValues(http.StatusBadRequest, recorder.Code) + + // 2. we should have an error message in the result body + result := recorder.Result() + defer result.Body.Close() + b, err := ioutil.ReadAll(result.Body) + assert.NoError(suite.T(), err) + assert.Equal(suite.T(), `{"error":"missing one or more required form values"}`, string(b)) +} + +// TestAccountCreatePOSTHandlerWeakPassword makes sure that the handler fails when a weak password is provided +func (suite *AccountTestSuite) TestAccountCreatePOSTHandlerWeakPassword() { + + // setup + recorder := httptest.NewRecorder() + 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.Form = suite.newUserFormHappyPath + // set a weak password + ctx.Request.Form.Set("password", "weak") + suite.accountModule.accountCreatePOSTHandler(ctx) + + // check response + suite.EqualValues(http.StatusBadRequest, recorder.Code) + + // 2. we should have an error message in the result body + result := recorder.Result() + defer result.Body.Close() + b, err := ioutil.ReadAll(result.Body) + assert.NoError(suite.T(), err) + assert.Equal(suite.T(), `{"error":"insecure password, try including more special characters, using uppercase letters, using numbers or using a longer password"}`, string(b)) +} + +// TestAccountCreatePOSTHandlerWeirdLocale makes sure that the handler fails when a weird locale is provided +func (suite *AccountTestSuite) TestAccountCreatePOSTHandlerWeirdLocale() { + + // setup + recorder := httptest.NewRecorder() + 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.Form = suite.newUserFormHappyPath + // set an invalid locale + ctx.Request.Form.Set("locale", "neverneverland") + suite.accountModule.accountCreatePOSTHandler(ctx) + + // check response + suite.EqualValues(http.StatusBadRequest, recorder.Code) + + // 2. we should have an error message in the result body + result := recorder.Result() + defer result.Body.Close() + b, err := ioutil.ReadAll(result.Body) + assert.NoError(suite.T(), err) + assert.Equal(suite.T(), `{"error":"language: tag is not well-formed"}`, string(b)) +} + +// TestAccountCreatePOSTHandlerRegistrationsClosed makes sure that the handler fails when registrations are closed +func (suite *AccountTestSuite) TestAccountCreatePOSTHandlerRegistrationsClosed() { + + // setup + recorder := httptest.NewRecorder() + 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.Form = suite.newUserFormHappyPath + + // close registrations + suite.config.AccountsConfig.OpenRegistration = false + suite.accountModule.accountCreatePOSTHandler(ctx) + + // check response + suite.EqualValues(http.StatusBadRequest, recorder.Code) + + // 2. we should have an error message in the result body + result := recorder.Result() + defer result.Body.Close() + b, err := ioutil.ReadAll(result.Body) + assert.NoError(suite.T(), err) + assert.Equal(suite.T(), `{"error":"registration is not open for this server"}`, string(b)) +} + +// TestAccountCreatePOSTHandlerReasonNotProvided makes sure that the handler fails when no reason is provided but one is required +func (suite *AccountTestSuite) TestAccountCreatePOSTHandlerReasonNotProvided() { + + // setup + recorder := httptest.NewRecorder() + 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.Form = suite.newUserFormHappyPath + + // remove reason + ctx.Request.Form.Set("reason", "") + + suite.accountModule.accountCreatePOSTHandler(ctx) + + // check response + suite.EqualValues(http.StatusBadRequest, recorder.Code) + + // 2. we should have an error message in the result body + result := recorder.Result() + defer result.Body.Close() + b, err := ioutil.ReadAll(result.Body) + assert.NoError(suite.T(), err) + assert.Equal(suite.T(), `{"error":"no reason provided"}`, string(b)) +} + +// TestAccountCreatePOSTHandlerReasonNotProvided makes sure that the handler fails when a crappy reason is presented but a good one is required +func (suite *AccountTestSuite) TestAccountCreatePOSTHandlerInsufficientReason() { + + // setup + recorder := httptest.NewRecorder() + 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.Form = suite.newUserFormHappyPath + + // remove reason + ctx.Request.Form.Set("reason", "just cuz") + + suite.accountModule.accountCreatePOSTHandler(ctx) + + // check response + suite.EqualValues(http.StatusBadRequest, recorder.Code) + + // 2. we should have an error message in the result body + result := recorder.Result() + defer result.Body.Close() + b, err := ioutil.ReadAll(result.Body) + assert.NoError(suite.T(), err) + assert.Equal(suite.T(), `{"error":"reason should be at least 40 chars but 'just cuz' was 8"}`, string(b)) +} + func TestAccountTestSuite(t *testing.T) { suite.Run(t, new(AccountTestSuite)) }