summaryrefslogtreecommitdiff
path: root/internal/api
diff options
context:
space:
mode:
Diffstat (limited to 'internal/api')
-rw-r--r--internal/api/client/account/accountupdate.go9
-rw-r--r--internal/api/client/account/accountupdate_test.go75
-rw-r--r--internal/api/client/status/statuscreate_test.go55
-rw-r--r--internal/api/model/account.go2
-rw-r--r--internal/api/model/source.go2
-rw-r--r--internal/api/model/status.go16
6 files changed, 143 insertions, 16 deletions
diff --git a/internal/api/client/account/accountupdate.go b/internal/api/client/account/accountupdate.go
index 786aefb38..3ba214ed1 100644
--- a/internal/api/client/account/accountupdate.go
+++ b/internal/api/client/account/accountupdate.go
@@ -88,6 +88,10 @@ import (
// in: formData
// description: Default language to use for authored statuses (ISO 6391).
// type: string
+// - name: source[status_format]
+// in: formData
+// description: Default format to use for authored statuses (plain or markdown).
+// type: string
//
// security:
// - OAuth2 Bearer:
@@ -163,6 +167,10 @@ func parseUpdateAccountForm(c *gin.Context) (*model.UpdateCredentialsRequest, er
form.Source.Language = &language
}
+ if statusFormat, ok := sourceMap["status_format"]; ok {
+ form.Source.StatusFormat = &statusFormat
+ }
+
if form == nil ||
(form.Discoverable == nil &&
form.Bot == nil &&
@@ -174,6 +182,7 @@ func parseUpdateAccountForm(c *gin.Context) (*model.UpdateCredentialsRequest, er
form.Source.Privacy == nil &&
form.Source.Sensitive == nil &&
form.Source.Language == nil &&
+ form.Source.StatusFormat == nil &&
form.FieldsAttributes == nil) {
return nil, errors.New("empty form submitted")
}
diff --git a/internal/api/client/account/accountupdate_test.go b/internal/api/client/account/accountupdate_test.go
index 91f886721..d59cd02a5 100644
--- a/internal/api/client/account/accountupdate_test.go
+++ b/internal/api/client/account/accountupdate_test.go
@@ -362,6 +362,81 @@ func (suite *AccountUpdateTestSuite) TestAccountUpdateCredentialsPATCHHandlerUpd
suite.True(apimodelAccount.Locked)
}
+func (suite *AccountUpdateTestSuite) TestAccountUpdateCredentialsPATCHHandlerUpdateStatusFormatOK() {
+ // set up the request
+ // we're updating the language of zork
+ requestBody, w, err := testrig.CreateMultipartFormData(
+ "", "",
+ map[string]string{
+ "source[status_format]": "markdown",
+ })
+ if err != nil {
+ panic(err)
+ }
+ bodyBytes := requestBody.Bytes()
+ recorder := httptest.NewRecorder()
+ ctx := suite.newContext(recorder, http.MethodPatch, bodyBytes, account.UpdateCredentialsPath, w.FormDataContentType())
+
+ // call the handler
+ suite.accountModule.AccountUpdateCredentialsPATCHHandler(ctx)
+
+ // 1. we should have OK because our request was valid
+ suite.Equal(http.StatusOK, recorder.Code)
+
+ // 2. we should have no error message in the result body
+ result := recorder.Result()
+ defer result.Body.Close()
+
+ // check the response
+ b, err := ioutil.ReadAll(result.Body)
+ suite.NoError(err)
+
+ // unmarshal the returned account
+ apimodelAccount := &apimodel.Account{}
+ err = json.Unmarshal(b, apimodelAccount)
+ suite.NoError(err)
+
+ // check the returned api model account
+ // fields should be updated
+ suite.Equal("markdown", apimodelAccount.Source.StatusFormat)
+
+ dbAccount, err := suite.db.GetAccountByID(context.Background(), suite.testAccounts["local_account_1"].ID)
+ if err != nil {
+ suite.FailNow(err.Error())
+ }
+ suite.Equal(dbAccount.StatusFormat, "markdown")
+}
+
+func (suite *AccountUpdateTestSuite) TestAccountUpdateCredentialsPATCHHandlerUpdateStatusFormatBad() {
+ // set up the request
+ // we're updating the language of zork
+ requestBody, w, err := testrig.CreateMultipartFormData(
+ "", "",
+ map[string]string{
+ "source[status_format]": "peepeepoopoo",
+ })
+ if err != nil {
+ panic(err)
+ }
+ bodyBytes := requestBody.Bytes()
+ recorder := httptest.NewRecorder()
+ ctx := suite.newContext(recorder, http.MethodPatch, bodyBytes, account.UpdateCredentialsPath, w.FormDataContentType())
+
+ // call the handler
+ suite.accountModule.AccountUpdateCredentialsPATCHHandler(ctx)
+
+ suite.Equal(http.StatusBadRequest, recorder.Code)
+
+ result := recorder.Result()
+ defer result.Body.Close()
+
+ // check the response
+ b, err := ioutil.ReadAll(result.Body)
+ suite.NoError(err)
+
+ suite.Equal(`{"error":"Bad Request: status format 'peepeepoopoo' was not recognized, valid options are 'plain', 'markdown'"}`, string(b))
+}
+
func TestAccountUpdateTestSuite(t *testing.T) {
suite.Run(t, new(AccountUpdateTestSuite))
}
diff --git a/internal/api/client/status/statuscreate_test.go b/internal/api/client/status/statuscreate_test.go
index 93fe74175..a42654a42 100644
--- a/internal/api/client/status/statuscreate_test.go
+++ b/internal/api/client/status/statuscreate_test.go
@@ -41,13 +41,11 @@ type StatusCreateTestSuite struct {
StatusStandardTestSuite
}
-var statusWithLinksAndTags = `#test alright, should be able to post #links with fragments in them now, let's see........
-
-https://docs.gotosocial.org/en/latest/user_guide/posts/#links
-
-#gotosocial
-
-(tobi remember to pull the docker image challenge)`
+const (
+ statusWithLinksAndTags = "#test alright, should be able to post #links with fragments in them now, let's see........\n\nhttps://docs.gotosocial.org/en/latest/user_guide/posts/#links\n\n#gotosocial\n\n(tobi remember to pull the docker image challenge)"
+ statusMarkdown = "# Title\n\n## Smaller title\n\nThis is a post written in [markdown](https://www.markdownguide.org/)\n\n<img src=\"https://d33wubrfki0l68.cloudfront.net/f1f475a6fda1c2c4be4cac04033db5c3293032b4/513a4/assets/images/markdown-mark-white.svg\"/>"
+ statusMarkdownExpected = "<h1>Title</h1>\n\n<h2>Smaller title</h2>\n\n<p>This is a post written in <a href=\"https://www.markdownguide.org/\" rel=\"nofollow noreferrer noopener\" target=\"_blank\">markdown</a></p>\n\n<p><img src=\"https://d33wubrfki0l68.cloudfront.net/f1f475a6fda1c2c4be4cac04033db5c3293032b4/513a4/assets/images/markdown-mark-white.svg\" crossorigin=\"anonymous\"/></p>\n"
+)
// Post a new status with some custom visibility settings
func (suite *StatusCreateTestSuite) TestPostNewStatus() {
@@ -104,6 +102,49 @@ func (suite *StatusCreateTestSuite) TestPostNewStatus() {
suite.Equal(statusReply.Account.ID, gtsTag.FirstSeenFromAccountID)
}
+func (suite *StatusCreateTestSuite) TestPostNewStatusMarkdown() {
+ // set default post language of account 1 to markdown
+ testAccount := suite.testAccounts["local_account_1"]
+ testAccount.StatusFormat = "markdown"
+
+ a, err := suite.db.UpdateAccount(context.Background(), testAccount)
+ if err != nil {
+ suite.FailNow(err.Error())
+ }
+ suite.Equal(a.StatusFormat, "markdown")
+
+ t := suite.testTokens["local_account_1"]
+ oauthToken := oauth.DBTokenToToken(t)
+
+ recorder := httptest.NewRecorder()
+ ctx, _ := testrig.CreateGinTestContext(recorder, nil)
+ ctx.Set(oauth.SessionAuthorizedApplication, suite.testApplications["application_1"])
+ ctx.Set(oauth.SessionAuthorizedToken, oauthToken)
+ ctx.Set(oauth.SessionAuthorizedUser, suite.testUsers["local_account_1"])
+ ctx.Set(oauth.SessionAuthorizedAccount, a)
+
+ ctx.Request = httptest.NewRequest(http.MethodPost, fmt.Sprintf("http://localhost:8080/%s", status.BasePath), nil)
+ ctx.Request.Header.Set("accept", "application/json")
+ ctx.Request.Form = url.Values{
+ "status": {statusMarkdown},
+ "visibility": {string(model.VisibilityPublic)},
+ }
+ suite.statusModule.StatusCreatePOSTHandler(ctx)
+
+ suite.EqualValues(http.StatusOK, recorder.Code)
+
+ result := recorder.Result()
+ defer result.Body.Close()
+ b, err := ioutil.ReadAll(result.Body)
+ suite.NoError(err)
+
+ statusReply := &model.Status{}
+ err = json.Unmarshal(b, statusReply)
+ suite.NoError(err)
+
+ suite.Equal(statusMarkdownExpected, statusReply.Content)
+}
+
// mention an account that is not yet known to the instance -- it should be looked up and put in the db
func (suite *StatusCreateTestSuite) TestMentionUnknownAccount() {
// first remove remote account 1 from the database so it gets looked up again
diff --git a/internal/api/model/account.go b/internal/api/model/account.go
index 4ff229589..dc6fa24b8 100644
--- a/internal/api/model/account.go
+++ b/internal/api/model/account.go
@@ -163,6 +163,8 @@ type UpdateSource struct {
Sensitive *bool `form:"sensitive" json:"sensitive" xml:"sensitive"`
// Default language to use for authored statuses. (ISO 6391)
Language *string `form:"language" json:"language" xml:"language"`
+ // Default format for authored statuses (plain or markdown).
+ StatusFormat *string `form:"status_format" json:"status_format" xml:"status_format"`
}
// UpdateField is to be used specifically in an UpdateCredentialsRequest.
diff --git a/internal/api/model/source.go b/internal/api/model/source.go
index 0ca8f2a6b..14f4ba7a9 100644
--- a/internal/api/model/source.go
+++ b/internal/api/model/source.go
@@ -31,6 +31,8 @@ type Source struct {
Sensitive bool `json:"sensitive,omitempty"`
// The default posting language for new statuses.
Language string `json:"language,omitempty"`
+ // The default posting format for new statuses.
+ StatusFormat string `json:"status_format"`
// Profile bio.
Note string `json:"note"`
// Metadata about the account.
diff --git a/internal/api/model/status.go b/internal/api/model/status.go
index 62efaf434..d3c7a0e4f 100644
--- a/internal/api/model/status.go
+++ b/internal/api/model/status.go
@@ -181,8 +181,8 @@ type StatusCreateRequest struct {
Language string `form:"language" json:"language" xml:"language"`
// Format to use when parsing this status.
// enum:
- // - markdown
// - plain
+ // - markdown
// in: formData
Format StatusFormat `form:"format" json:"format" xml:"format"`
}
@@ -245,11 +245,9 @@ type AdvancedVisibilityFlagsForm struct {
// example: plain
type StatusFormat string
-// StatusFormatPlain expects a plaintext status which will then be formatted into html.
-const StatusFormatPlain StatusFormat = "plain"
-
-// StatusFormatMarkdown expects a markdown formatted status, which will then be formatted into html.
-const StatusFormatMarkdown StatusFormat = "markdown"
-
-// StatusFormatDefault is the format that should be used when nothing else is specified.
-const StatusFormatDefault StatusFormat = StatusFormatPlain
+// Format to use when parsing submitted status into an html-formatted status
+const (
+ StatusFormatPlain StatusFormat = "plain"
+ StatusFormatMarkdown StatusFormat = "markdown"
+ StatusFormatDefault StatusFormat = StatusFormatPlain
+)