diff options
| author | 2025-10-15 18:57:57 +0200 | |
|---|---|---|
| committer | 2025-10-17 15:33:49 +0200 | |
| commit | 6fee55dcff976f3eeae5879fe91d2f27780d0da4 (patch) | |
| tree | d028c3ac30a84fc6095c9ca9dd4d136f905d8887 /internal/api | |
| parent | [bugfix] Fix HTTP return code for Likes of remote statuses (#4504) (diff) | |
| download | gotosocial-6fee55dcff976f3eeae5879fe91d2f27780d0da4.tar.xz | |
[chore] Rationalize HTTP return codes for fedi endpoints, other tidying up (#4503)
# Description
> If this is a code change, please include a summary of what you've coded, and link to the issue(s) it closes/implements.
>
> If this is a documentation change, please briefly describe what you've changed and why.
This pull request does some refactoring of the fedi API endpoints and processing functions, and the authenticate + pub key deref functions, to try to return fewer silly HTTP codes like 410 Gone (when a *remote* account is gone, not a local one), and 500 errors where something isn't really an error.
Also does some general tidying up and renaming for consistency.
## Checklist
Please put an x inside each checkbox to indicate that you've read and followed it: `[ ]` -> `[x]`
If this is a documentation change, only the first checkbox must be filled (you can delete the others if you want).
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [x] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
- [x] I/we have performed a self-review of added code.
- [x] I/we have written code that is legible and maintainable by others.
- [x] I/we have commented the added code, particularly in hard-to-understand areas.
- [ ] I/we have made any necessary changes to documentation.
- [ ] I/we have added tests that cover new code.
- [x] I/we have run tests and they pass locally with the changes.
- [x] I/we have run `go fmt ./...` and `golangci-lint run`.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4503
Co-authored-by: tobi <tobi.smethurst@protonmail.com>
Co-committed-by: tobi <tobi.smethurst@protonmail.com>
Diffstat (limited to 'internal/api')
19 files changed, 99 insertions, 118 deletions
diff --git a/internal/api/activitypub/emoji/emoji.go b/internal/api/activitypub/emoji/emoji.go index 361a3bbc7..e218af9ad 100644 --- a/internal/api/activitypub/emoji/emoji.go +++ b/internal/api/activitypub/emoji/emoji.go @@ -20,16 +20,12 @@ package emoji import ( "net/http" + apiutil "code.superseriousbusiness.org/gotosocial/internal/api/util" "code.superseriousbusiness.org/gotosocial/internal/processing" "github.com/gin-gonic/gin" ) -const ( - // EmojiIDKey is for emoji IDs - EmojiIDKey = "id" - // EmojiBasePath is the base path for serving AP Emojis, minus the "emoji" prefix - EmojiWithIDPath = "/:" + EmojiIDKey -) +const EmojiWithIDPath = "/:" + apiutil.IDKey type Module struct { processor *processing.Processor diff --git a/internal/api/activitypub/emoji/emojiget.go b/internal/api/activitypub/emoji/emojiget.go index cc0049f89..fc6740c9b 100644 --- a/internal/api/activitypub/emoji/emojiget.go +++ b/internal/api/activitypub/emoji/emojiget.go @@ -28,8 +28,8 @@ import ( ) func (m *Module) EmojiGetHandler(c *gin.Context) { - requestedEmojiID := strings.ToUpper(c.Param(EmojiIDKey)) - if requestedEmojiID == "" { + emojiID := strings.ToUpper(c.Param(apiutil.IDKey)) + if emojiID == "" { err := errors.New("no emoji id specified in request") apiutil.ErrorHandler(c, gtserror.NewErrorBadRequest(err, err.Error()), m.processor.InstanceGetV1) return @@ -41,7 +41,7 @@ func (m *Module) EmojiGetHandler(c *gin.Context) { return } - resp, errWithCode := m.processor.Fedi().EmojiGet(c.Request.Context(), requestedEmojiID) + resp, errWithCode := m.processor.Fedi().EmojiGet(c.Request.Context(), emojiID) if errWithCode != nil { apiutil.ErrorHandler(c, errWithCode, m.processor.InstanceGetV1) return diff --git a/internal/api/activitypub/emoji/emojiget_test.go b/internal/api/activitypub/emoji/emojiget_test.go index 071cb80b6..9cc13f978 100644 --- a/internal/api/activitypub/emoji/emojiget_test.go +++ b/internal/api/activitypub/emoji/emojiget_test.go @@ -25,6 +25,7 @@ import ( "code.superseriousbusiness.org/gotosocial/internal/admin" "code.superseriousbusiness.org/gotosocial/internal/api/activitypub/emoji" + apiutil "code.superseriousbusiness.org/gotosocial/internal/api/util" "code.superseriousbusiness.org/gotosocial/internal/db" "code.superseriousbusiness.org/gotosocial/internal/email" "code.superseriousbusiness.org/gotosocial/internal/federation" @@ -122,7 +123,7 @@ func (suite *EmojiGetTestSuite) TestGetEmoji() { // but because we're calling the function directly, we need to set them manually. ctx.Params = gin.Params{ gin.Param{ - Key: emoji.EmojiIDKey, + Key: apiutil.IDKey, Value: targetEmoji.ID, }, } diff --git a/internal/api/activitypub/publickey/publickey.go b/internal/api/activitypub/publickey/publickey.go index 161123048..eaca9a39b 100644 --- a/internal/api/activitypub/publickey/publickey.go +++ b/internal/api/activitypub/publickey/publickey.go @@ -20,17 +20,14 @@ package publickey import ( "net/http" + apiutil "code.superseriousbusiness.org/gotosocial/internal/api/util" + "code.superseriousbusiness.org/gotosocial/internal/processing" "code.superseriousbusiness.org/gotosocial/internal/uris" "github.com/gin-gonic/gin" ) -const ( - // UsernameKey is for account usernames. - UsernameKey = "username" - // PublicKeyPath is a path to a user's public key, for serving bare minimum AP representations. - PublicKeyPath = "users/:" + UsernameKey + "/" + uris.PublicKeyPath -) +const PublicKeyPath = "users/:" + apiutil.UsernameKey + "/" + uris.PublicKeyPath type Module struct { processor *processing.Processor diff --git a/internal/api/activitypub/publickey/publickeyget.go b/internal/api/activitypub/publickey/publickeyget.go index 6e050a3b5..f1b07c2d2 100644 --- a/internal/api/activitypub/publickey/publickeyget.go +++ b/internal/api/activitypub/publickey/publickeyget.go @@ -34,8 +34,8 @@ import ( // public key, username, and type of the account. func (m *Module) PublicKeyGETHandler(c *gin.Context) { // usernames on our instance are always lowercase - requestedUsername := strings.ToLower(c.Param(UsernameKey)) - if requestedUsername == "" { + requestedUser := strings.ToLower(c.Param(apiutil.UsernameKey)) + if requestedUser == "" { err := errors.New("no username specified in request") apiutil.ErrorHandler(c, gtserror.NewErrorBadRequest(err, err.Error()), m.processor.InstanceGetV1) return @@ -47,13 +47,17 @@ func (m *Module) PublicKeyGETHandler(c *gin.Context) { return } + // If HTML is requested, redirect + // to user's profile instead. if contentType == string(apiutil.TextHTML) { - // redirect to the user's profile - c.Redirect(http.StatusSeeOther, "/@"+requestedUsername) + c.Redirect(http.StatusSeeOther, "/@"+requestedUser) return } - resp, errWithCode := m.processor.Fedi().UserGet(c.Request.Context(), requestedUsername, c.Request.URL) + resp, errWithCode := m.processor.Fedi().UserGetMinimal( + c.Request.Context(), + requestedUser, + ) if errWithCode != nil { apiutil.ErrorHandler(c, errWithCode, m.processor.InstanceGetV1) return diff --git a/internal/api/activitypub/users/featured.go b/internal/api/activitypub/users/featured.go index 90b368b26..021e5aeb9 100644 --- a/internal/api/activitypub/users/featured.go +++ b/internal/api/activitypub/users/featured.go @@ -67,8 +67,8 @@ import ( // description: not found func (m *Module) FeaturedCollectionGETHandler(c *gin.Context) { // usernames on our instance are always lowercase - requestedUsername := strings.ToLower(c.Param(UsernameKey)) - if requestedUsername == "" { + requestedUser := strings.ToLower(c.Param(apiutil.UsernameKey)) + if requestedUser == "" { err := errors.New("no username specified in request") apiutil.ErrorHandler(c, gtserror.NewErrorBadRequest(err, err.Error()), m.processor.InstanceGetV1) return @@ -83,11 +83,11 @@ func (m *Module) FeaturedCollectionGETHandler(c *gin.Context) { if contentType == string(apiutil.TextHTML) { // This isn't an ActivityPub request; // redirect to the user's profile. - c.Redirect(http.StatusSeeOther, "/@"+requestedUsername) + c.Redirect(http.StatusSeeOther, "/@"+requestedUser) return } - resp, errWithCode := m.processor.Fedi().FeaturedCollectionGet(c.Request.Context(), requestedUsername) + resp, errWithCode := m.processor.Fedi().FeaturedCollectionGet(c.Request.Context(), requestedUser) if errWithCode != nil { apiutil.ErrorHandler(c, errWithCode, m.processor.InstanceGetV1) return diff --git a/internal/api/activitypub/users/followers.go b/internal/api/activitypub/users/followers.go index f00b7bc40..4815df944 100644 --- a/internal/api/activitypub/users/followers.go +++ b/internal/api/activitypub/users/followers.go @@ -31,8 +31,8 @@ import ( // FollowersGETHandler returns a collection of URIs for followers of the target user, formatted so that other AP servers can understand it. func (m *Module) FollowersGETHandler(c *gin.Context) { // usernames on our instance are always lowercase - requestedUsername := strings.ToLower(c.Param(UsernameKey)) - if requestedUsername == "" { + requestedUser := strings.ToLower(c.Param(apiutil.UsernameKey)) + if requestedUser == "" { err := errors.New("no username specified in request") apiutil.ErrorHandler(c, gtserror.NewErrorBadRequest(err, err.Error()), m.processor.InstanceGetV1) return @@ -47,7 +47,7 @@ func (m *Module) FollowersGETHandler(c *gin.Context) { if contentType == string(apiutil.TextHTML) { // This isn't an ActivityPub request; // redirect to the user's profile. - c.Redirect(http.StatusSeeOther, "/@"+requestedUsername) + c.Redirect(http.StatusSeeOther, "/@"+requestedUser) return } @@ -61,7 +61,7 @@ func (m *Module) FollowersGETHandler(c *gin.Context) { return } - resp, errWithCode := m.processor.Fedi().FollowersGet(c.Request.Context(), requestedUsername, page) + resp, errWithCode := m.processor.Fedi().FollowersGet(c.Request.Context(), requestedUser, page) if errWithCode != nil { apiutil.ErrorHandler(c, errWithCode, m.processor.InstanceGetV1) return diff --git a/internal/api/activitypub/users/following.go b/internal/api/activitypub/users/following.go index 630e0b821..ccc5ce641 100644 --- a/internal/api/activitypub/users/following.go +++ b/internal/api/activitypub/users/following.go @@ -31,8 +31,8 @@ import ( // FollowingGETHandler returns a collection of URIs for accounts that the target user follows, formatted so that other AP servers can understand it. func (m *Module) FollowingGETHandler(c *gin.Context) { // usernames on our instance are always lowercase - requestedUsername := strings.ToLower(c.Param(UsernameKey)) - if requestedUsername == "" { + requestedUser := strings.ToLower(c.Param(apiutil.UsernameKey)) + if requestedUser == "" { err := errors.New("no username specified in request") apiutil.ErrorHandler(c, gtserror.NewErrorBadRequest(err, err.Error()), m.processor.InstanceGetV1) return @@ -47,7 +47,7 @@ func (m *Module) FollowingGETHandler(c *gin.Context) { if contentType == string(apiutil.TextHTML) { // This isn't an ActivityPub request; // redirect to the user's profile. - c.Redirect(http.StatusSeeOther, "/@"+requestedUsername) + c.Redirect(http.StatusSeeOther, "/@"+requestedUser) return } @@ -61,7 +61,7 @@ func (m *Module) FollowingGETHandler(c *gin.Context) { return } - resp, errWithCode := m.processor.Fedi().FollowingGet(c.Request.Context(), requestedUsername, page) + resp, errWithCode := m.processor.Fedi().FollowingGet(c.Request.Context(), requestedUser, page) if errWithCode != nil { apiutil.ErrorHandler(c, errWithCode, m.processor.InstanceGetV1) return diff --git a/internal/api/activitypub/users/inboxpost_test.go b/internal/api/activitypub/users/inboxpost_test.go index 51df35672..facf2b459 100644 --- a/internal/api/activitypub/users/inboxpost_test.go +++ b/internal/api/activitypub/users/inboxpost_test.go @@ -31,7 +31,7 @@ import ( "code.superseriousbusiness.org/activity/streams" "code.superseriousbusiness.org/activity/streams/vocab" "code.superseriousbusiness.org/gotosocial/internal/ap" - "code.superseriousbusiness.org/gotosocial/internal/api/activitypub/users" + apiutil "code.superseriousbusiness.org/gotosocial/internal/api/util" "code.superseriousbusiness.org/gotosocial/internal/db" "code.superseriousbusiness.org/gotosocial/internal/gtserror" "code.superseriousbusiness.org/gotosocial/internal/gtsmodel" @@ -79,7 +79,7 @@ func (suite *InboxPostTestSuite) inboxPost( ) // Put the request together. - ctx.AddParam(users.UsernameKey, targetAccount.Username) + ctx.AddParam(apiutil.UsernameKey, targetAccount.Username) ctx.Request = httptest.NewRequest(http.MethodPost, targetAccount.InboxURI, bytes.NewReader(b)) ctx.Request.Header.Set("Signature", signature) ctx.Request.Header.Set("Date", dateHeader) diff --git a/internal/api/activitypub/users/outboxget.go b/internal/api/activitypub/users/outboxget.go index 64bcc195b..a76834ce0 100644 --- a/internal/api/activitypub/users/outboxget.go +++ b/internal/api/activitypub/users/outboxget.go @@ -84,8 +84,8 @@ import ( // description: not found func (m *Module) OutboxGETHandler(c *gin.Context) { // usernames on our instance are always lowercase - requestedUsername := strings.ToLower(c.Param(UsernameKey)) - if requestedUsername == "" { + requestedUser := strings.ToLower(c.Param(apiutil.UsernameKey)) + if requestedUser == "" { err := errors.New("no username specified in request") apiutil.ErrorHandler(c, gtserror.NewErrorBadRequest(err, err.Error()), m.processor.InstanceGetV1) return @@ -100,7 +100,7 @@ func (m *Module) OutboxGETHandler(c *gin.Context) { if contentType == string(apiutil.TextHTML) { // This isn't an ActivityPub request; // redirect to the user's profile. - c.Redirect(http.StatusSeeOther, "/@"+requestedUsername) + c.Redirect(http.StatusSeeOther, "/@"+requestedUser) return } @@ -114,7 +114,7 @@ func (m *Module) OutboxGETHandler(c *gin.Context) { return } - resp, errWithCode := m.processor.Fedi().OutboxGet(c.Request.Context(), requestedUsername, page) + resp, errWithCode := m.processor.Fedi().OutboxGet(c.Request.Context(), requestedUser, page) if errWithCode != nil { apiutil.ErrorHandler(c, errWithCode, m.processor.InstanceGetV1) return diff --git a/internal/api/activitypub/users/outboxget_test.go b/internal/api/activitypub/users/outboxget_test.go index 1290830b2..23d139182 100644 --- a/internal/api/activitypub/users/outboxget_test.go +++ b/internal/api/activitypub/users/outboxget_test.go @@ -28,7 +28,7 @@ import ( "code.superseriousbusiness.org/activity/streams" "code.superseriousbusiness.org/activity/streams/vocab" - "code.superseriousbusiness.org/gotosocial/internal/api/activitypub/users" + apiutil "code.superseriousbusiness.org/gotosocial/internal/api/util" "code.superseriousbusiness.org/gotosocial/testrig" "github.com/gin-gonic/gin" "github.com/stretchr/testify/suite" @@ -59,7 +59,7 @@ func (suite *OutboxGetTestSuite) TestGetOutbox() { // but because we're calling the function directly, we need to set them manually. ctx.Params = gin.Params{ gin.Param{ - Key: users.UsernameKey, + Key: apiutil.UsernameKey, Value: targetAccount.Username, }, } @@ -85,7 +85,7 @@ func (suite *OutboxGetTestSuite) TestGetOutbox() { "type": "OrderedCollection" }`, dst.String()) - m := make(map[string]interface{}) + m := make(map[string]any) err = json.Unmarshal(b, &m) suite.NoError(err) @@ -117,7 +117,7 @@ func (suite *OutboxGetTestSuite) TestGetOutboxFirstPage() { // but because we're calling the function directly, we need to set them manually. ctx.Params = gin.Params{ gin.Param{ - Key: users.UsernameKey, + Key: apiutil.UsernameKey, Value: targetAccount.Username, }, } @@ -172,7 +172,7 @@ func (suite *OutboxGetTestSuite) TestGetOutboxFirstPage() { "type": "OrderedCollectionPage" }`, dst.String()) - m := make(map[string]interface{}) + m := make(map[string]any) err = json.Unmarshal(b, &m) suite.NoError(err) @@ -204,11 +204,11 @@ func (suite *OutboxGetTestSuite) TestGetOutboxNextPage() { // but because we're calling the function directly, we need to set them manually. ctx.Params = gin.Params{ gin.Param{ - Key: users.UsernameKey, + Key: apiutil.UsernameKey, Value: targetAccount.Username, }, gin.Param{ - Key: users.MaxIDKey, + Key: apiutil.MaxIDKey, Value: "01F8MHAMCHF6Y650WCRSCP4WMY", }, } @@ -235,7 +235,7 @@ func (suite *OutboxGetTestSuite) TestGetOutboxNextPage() { "type": "OrderedCollectionPage" }`, dst.String()) - m := make(map[string]interface{}) + m := make(map[string]any) err = json.Unmarshal(b, &m) suite.NoError(err) @@ -261,7 +261,7 @@ func checkDropPublished(t *testing.T, b []byte, at ...string) []byte { entries := make([]map[string]any, 0) for _, key := range at { switch vt := m[key].(type) { - case []interface{}: + case []any: for _, t := range vt { if entry, ok := t.(map[string]any); ok { entries = append(entries, entry) diff --git a/internal/api/activitypub/users/repliesget.go b/internal/api/activitypub/users/repliesget.go index 3a8a81bfb..facbbcc85 100644 --- a/internal/api/activitypub/users/repliesget.go +++ b/internal/api/activitypub/users/repliesget.go @@ -91,15 +91,15 @@ import ( // description: not found func (m *Module) StatusRepliesGETHandler(c *gin.Context) { // usernames on our instance are always lowercase - requestedUsername := strings.ToLower(c.Param(UsernameKey)) - if requestedUsername == "" { + requestedUser := strings.ToLower(c.Param(apiutil.UsernameKey)) + if requestedUser == "" { err := errors.New("no username specified in request") apiutil.ErrorHandler(c, gtserror.NewErrorBadRequest(err, err.Error()), m.processor.InstanceGetV1) return } // status IDs on our instance are always uppercase - requestedStatusID := strings.ToUpper(c.Param(StatusIDKey)) + requestedStatusID := strings.ToUpper(c.Param(apiutil.IDKey)) if requestedStatusID == "" { err := errors.New("no status id specified in request") apiutil.ErrorHandler(c, gtserror.NewErrorBadRequest(err, err.Error()), m.processor.InstanceGetV1) @@ -114,7 +114,7 @@ func (m *Module) StatusRepliesGETHandler(c *gin.Context) { if contentType == string(apiutil.TextHTML) { // redirect to the status - c.Redirect(http.StatusSeeOther, "/@"+requestedUsername+"/statuses/"+requestedStatusID) + c.Redirect(http.StatusSeeOther, "/@"+requestedUser+"/statuses/"+requestedStatusID) return } @@ -150,7 +150,7 @@ func (m *Module) StatusRepliesGETHandler(c *gin.Context) { // Fetch serialized status replies response for input status. resp, errWithCode := m.processor.Fedi().StatusRepliesGet( c.Request.Context(), - requestedUsername, + requestedUser, requestedStatusID, page, onlyOtherAccounts, diff --git a/internal/api/activitypub/users/repliesget_test.go b/internal/api/activitypub/users/repliesget_test.go index 5d3754a8c..f50424626 100644 --- a/internal/api/activitypub/users/repliesget_test.go +++ b/internal/api/activitypub/users/repliesget_test.go @@ -28,7 +28,7 @@ import ( "code.superseriousbusiness.org/activity/streams" "code.superseriousbusiness.org/activity/streams/vocab" "code.superseriousbusiness.org/gotosocial/internal/ap" - "code.superseriousbusiness.org/gotosocial/internal/api/activitypub/users" + apiutil "code.superseriousbusiness.org/gotosocial/internal/api/util" "code.superseriousbusiness.org/gotosocial/testrig" "github.com/gin-gonic/gin" "github.com/stretchr/testify/assert" @@ -61,11 +61,11 @@ func (suite *RepliesGetTestSuite) TestGetReplies() { // but because we're calling the function directly, we need to set them manually. ctx.Params = gin.Params{ gin.Param{ - Key: users.UsernameKey, + Key: apiutil.UsernameKey, Value: targetAccount.Username, }, gin.Param{ - Key: users.StatusIDKey, + Key: apiutil.IDKey, Value: targetStatus.ID, }, } @@ -96,7 +96,7 @@ func (suite *RepliesGetTestSuite) TestGetReplies() { }) assert.Equal(suite.T(), expect, string(b)) - m := make(map[string]interface{}) + m := make(map[string]any) err = json.Unmarshal(b, &m) assert.NoError(suite.T(), err) @@ -129,11 +129,11 @@ func (suite *RepliesGetTestSuite) TestGetRepliesNext() { // but because we're calling the function directly, we need to set them manually. ctx.Params = gin.Params{ gin.Param{ - Key: users.UsernameKey, + Key: apiutil.UsernameKey, Value: targetAccount.Username, }, gin.Param{ - Key: users.StatusIDKey, + Key: apiutil.IDKey, Value: targetStatus.ID, }, } @@ -167,7 +167,7 @@ func (suite *RepliesGetTestSuite) TestGetRepliesNext() { }) assert.Equal(suite.T(), expect, string(b)) - m := make(map[string]interface{}) + m := make(map[string]any) err = json.Unmarshal(b, &m) assert.NoError(suite.T(), err) @@ -202,11 +202,11 @@ func (suite *RepliesGetTestSuite) TestGetRepliesLast() { // but because we're calling the function directly, we need to set them manually. ctx.Params = gin.Params{ gin.Param{ - Key: users.UsernameKey, + Key: apiutil.UsernameKey, Value: targetAccount.Username, }, gin.Param{ - Key: users.StatusIDKey, + Key: apiutil.IDKey, Value: targetStatus.ID, }, } @@ -238,7 +238,7 @@ func (suite *RepliesGetTestSuite) TestGetRepliesLast() { }) assert.Equal(suite.T(), expect, string(b)) - m := make(map[string]interface{}) + m := make(map[string]any) err = json.Unmarshal(b, &m) assert.NoError(suite.T(), err) diff --git a/internal/api/activitypub/users/statusget.go b/internal/api/activitypub/users/statusget.go index 45b7847bf..843c3c2ff 100644 --- a/internal/api/activitypub/users/statusget.go +++ b/internal/api/activitypub/users/statusget.go @@ -30,15 +30,15 @@ import ( // StatusGETHandler serves the target status as an activitystreams NOTE so that other AP servers can parse it. func (m *Module) StatusGETHandler(c *gin.Context) { // usernames on our instance are always lowercase - requestedUsername := strings.ToLower(c.Param(UsernameKey)) - if requestedUsername == "" { + requestedUser := strings.ToLower(c.Param(apiutil.UsernameKey)) + if requestedUser == "" { err := errors.New("no username specified in request") apiutil.ErrorHandler(c, gtserror.NewErrorBadRequest(err, err.Error()), m.processor.InstanceGetV1) return } // status IDs on our instance are always uppercase - requestedStatusID := strings.ToUpper(c.Param(StatusIDKey)) + requestedStatusID := strings.ToUpper(c.Param(apiutil.IDKey)) if requestedStatusID == "" { err := errors.New("no status id specified in request") apiutil.ErrorHandler(c, gtserror.NewErrorBadRequest(err, err.Error()), m.processor.InstanceGetV1) @@ -53,11 +53,11 @@ func (m *Module) StatusGETHandler(c *gin.Context) { if contentType == string(apiutil.TextHTML) { // redirect to the status - c.Redirect(http.StatusSeeOther, "/@"+requestedUsername+"/statuses/"+requestedStatusID) + c.Redirect(http.StatusSeeOther, "/@"+requestedUser+"/statuses/"+requestedStatusID) return } - resp, errWithCode := m.processor.Fedi().StatusGet(c.Request.Context(), requestedUsername, requestedStatusID) + resp, errWithCode := m.processor.Fedi().StatusGet(c.Request.Context(), requestedUser, requestedStatusID) if errWithCode != nil { apiutil.ErrorHandler(c, errWithCode, m.processor.InstanceGetV1) return diff --git a/internal/api/activitypub/users/statusget_test.go b/internal/api/activitypub/users/statusget_test.go index 275acdc02..99386c5bb 100644 --- a/internal/api/activitypub/users/statusget_test.go +++ b/internal/api/activitypub/users/statusget_test.go @@ -27,7 +27,7 @@ import ( "code.superseriousbusiness.org/activity/streams" "code.superseriousbusiness.org/activity/streams/vocab" - "code.superseriousbusiness.org/gotosocial/internal/api/activitypub/users" + apiutil "code.superseriousbusiness.org/gotosocial/internal/api/util" "code.superseriousbusiness.org/gotosocial/testrig" "github.com/gin-gonic/gin" "github.com/stretchr/testify/suite" @@ -59,11 +59,11 @@ func (suite *StatusGetTestSuite) TestGetStatus() { // but because we're calling the function directly, we need to set them manually. ctx.Params = gin.Params{ gin.Param{ - Key: users.UsernameKey, + Key: apiutil.UsernameKey, Value: targetAccount.Username, }, gin.Param{ - Key: users.StatusIDKey, + Key: apiutil.IDKey, Value: targetStatus.ID, }, } @@ -80,7 +80,7 @@ func (suite *StatusGetTestSuite) TestGetStatus() { suite.NoError(err) // should be a Note - m := make(map[string]interface{}) + m := make(map[string]any) err = json.Unmarshal(b, &m) suite.NoError(err) @@ -118,11 +118,11 @@ func (suite *StatusGetTestSuite) TestGetStatusLowercase() { // but because we're calling the function directly, we need to set them manually. ctx.Params = gin.Params{ gin.Param{ - Key: users.UsernameKey, + Key: apiutil.UsernameKey, Value: strings.ToLower(targetAccount.Username), }, gin.Param{ - Key: users.StatusIDKey, + Key: apiutil.IDKey, Value: strings.ToLower(targetStatus.ID), }, } @@ -139,7 +139,7 @@ func (suite *StatusGetTestSuite) TestGetStatusLowercase() { suite.NoError(err) // should be a Note - m := make(map[string]interface{}) + m := make(map[string]any) err = json.Unmarshal(b, &m) suite.NoError(err) diff --git a/internal/api/activitypub/users/user.go b/internal/api/activitypub/users/user.go index 7fb5f6aa5..e55608fe2 100644 --- a/internal/api/activitypub/users/user.go +++ b/internal/api/activitypub/users/user.go @@ -27,39 +27,17 @@ import ( ) const ( - // UsernameKey is for account usernames. - UsernameKey = "username" - // StatusIDKey is for status IDs - StatusIDKey = "status" - // OnlyOtherAccountsKey is for filtering status responses. - OnlyOtherAccountsKey = "only_other_accounts" - // MinIDKey is for filtering status responses. - MinIDKey = "min_id" - // MaxIDKey is for filtering status responses. - MaxIDKey = "max_id" - // PageKey is for filtering status responses. - PageKey = "page" - - // BasePath is the base path for serving AP 'users' requests, minus the 'users' prefix. - BasePath = "/:" + UsernameKey - // InboxPath is for serving POST requests to a user's inbox with the given username key. - InboxPath = BasePath + "/" + uris.InboxPath - // OutboxPath is for serving GET requests to a user's outbox with the given username key. - OutboxPath = BasePath + "/" + uris.OutboxPath - // FollowersPath is for serving GET request's to a user's followers list, with the given username key. - FollowersPath = BasePath + "/" + uris.FollowersPath - // FollowingPath is for serving GET request's to a user's following list, with the given username key. - FollowingPath = BasePath + "/" + uris.FollowingPath - // FeaturedCollectionPath is for serving GET requests to a user's list of featured (pinned) statuses. + OnlyOtherAccountsKey = "only_other_accounts" + BasePath = "/:" + apiutil.UsernameKey + InboxPath = BasePath + "/" + uris.InboxPath + OutboxPath = BasePath + "/" + uris.OutboxPath + FollowersPath = BasePath + "/" + uris.FollowersPath + FollowingPath = BasePath + "/" + uris.FollowingPath FeaturedCollectionPath = BasePath + "/" + uris.CollectionsPath + "/" + uris.FeaturedPath - // StatusPath is for serving GET requests to a particular status by a user, with the given username key and status ID - StatusPath = BasePath + "/" + uris.StatusesPath + "/:" + StatusIDKey - // StatusRepliesPath is for serving the replies collection of a status. - StatusRepliesPath = StatusPath + "/replies" - // AcceptPath is for serving accepts of a status. - AcceptPath = BasePath + "/" + uris.AcceptsPath + "/:" + apiutil.IDKey - // AuthorizationsPath is for serving authorizations of an interaction. - AuthorizationsPath = BasePath + "/" + uris.AuthorizationsPath + "/:" + apiutil.IDKey + StatusPath = BasePath + "/" + uris.StatusesPath + "/:" + apiutil.IDKey + StatusRepliesPath = StatusPath + "/replies" + AcceptPath = BasePath + "/" + uris.AcceptsPath + "/:" + apiutil.IDKey + AuthorizationsPath = BasePath + "/" + uris.AuthorizationsPath + "/:" + apiutil.IDKey ) type Module struct { diff --git a/internal/api/activitypub/users/userget.go b/internal/api/activitypub/users/userget.go index 00d8a0f1f..9841e08d6 100644 --- a/internal/api/activitypub/users/userget.go +++ b/internal/api/activitypub/users/userget.go @@ -38,8 +38,8 @@ import ( // request is blocked. func (m *Module) UsersGETHandler(c *gin.Context) { // usernames on our instance are always lowercase - requestedUsername := strings.ToLower(c.Param(UsernameKey)) - if requestedUsername == "" { + requestedUser := strings.ToLower(c.Param(apiutil.UsernameKey)) + if requestedUser == "" { err := errors.New("no username specified in request") apiutil.ErrorHandler(c, gtserror.NewErrorBadRequest(err, err.Error()), m.processor.InstanceGetV1) return @@ -51,13 +51,17 @@ func (m *Module) UsersGETHandler(c *gin.Context) { return } + // If HTML is requested, redirect + // to user's profile instead. if contentType == string(apiutil.TextHTML) { - // redirect to the user's profile - c.Redirect(http.StatusSeeOther, "/@"+requestedUsername) + c.Redirect(http.StatusSeeOther, "/@"+requestedUser) return } - resp, errWithCode := m.processor.Fedi().UserGet(c.Request.Context(), requestedUsername, c.Request.URL) + resp, errWithCode := m.processor.Fedi().UserGet( + c.Request.Context(), + requestedUser, + ) if errWithCode != nil { apiutil.ErrorHandler(c, errWithCode, m.processor.InstanceGetV1) return diff --git a/internal/api/activitypub/users/userget_test.go b/internal/api/activitypub/users/userget_test.go index a9cba468f..648687d6e 100644 --- a/internal/api/activitypub/users/userget_test.go +++ b/internal/api/activitypub/users/userget_test.go @@ -27,6 +27,7 @@ import ( "code.superseriousbusiness.org/activity/streams" "code.superseriousbusiness.org/activity/streams/vocab" "code.superseriousbusiness.org/gotosocial/internal/api/activitypub/users" + apiutil "code.superseriousbusiness.org/gotosocial/internal/api/util" "code.superseriousbusiness.org/gotosocial/testrig" "github.com/gin-gonic/gin" "github.com/stretchr/testify/suite" @@ -57,7 +58,7 @@ func (suite *UserGetTestSuite) TestGetUser() { // but because we're calling the function directly, we need to set them manually. ctx.Params = gin.Params{ gin.Param{ - Key: users.UsernameKey, + Key: apiutil.UsernameKey, Value: targetAccount.Username, }, } @@ -74,7 +75,7 @@ func (suite *UserGetTestSuite) TestGetUser() { suite.NoError(err) // should be a Person - m := make(map[string]interface{}) + m := make(map[string]any) err = json.Unmarshal(b, &m) suite.NoError(err) @@ -125,7 +126,7 @@ func (suite *UserGetTestSuite) TestGetUserPublicKeyDeleted() { // but because we're calling the function directly, we need to set them manually. ctx.Params = gin.Params{ gin.Param{ - Key: users.UsernameKey, + Key: apiutil.UsernameKey, Value: targetAccount.Username, }, } @@ -142,7 +143,7 @@ func (suite *UserGetTestSuite) TestGetUserPublicKeyDeleted() { suite.NoError(err) // should be a Person - m := make(map[string]interface{}) + m := make(map[string]any) err = json.Unmarshal(b, &m) suite.NoError(err) diff --git a/internal/api/wellknown/webfinger/webfingerget.go b/internal/api/wellknown/webfinger/webfingerget.go index e277622fd..7c8f1cf84 100644 --- a/internal/api/wellknown/webfinger/webfingerget.go +++ b/internal/api/wellknown/webfinger/webfingerget.go @@ -67,7 +67,7 @@ func (m *Module) WebfingerGETRequest(c *gin.Context) { return } - requestedUsername, requestedHost, err := util.ExtractWebfingerParts(resourceQuery) + requestedUser, requestedHost, err := util.ExtractWebfingerParts(resourceQuery) if err != nil { err := fmt.Errorf("bad webfinger request with resource query %s: %w", resourceQuery, err) apiutil.ErrorHandler(c, gtserror.NewErrorBadRequest(err, err.Error()), m.processor.InstanceGetV1) @@ -80,7 +80,7 @@ func (m *Module) WebfingerGETRequest(c *gin.Context) { return } - resp, errWithCode := m.processor.Fedi().WebfingerGet(c.Request.Context(), requestedUsername) + resp, errWithCode := m.processor.Fedi().WebfingerGet(c.Request.Context(), requestedUser) if errWithCode != nil { apiutil.ErrorHandler(c, errWithCode, m.processor.InstanceGetV1) return |
