diff options
author | 2023-02-02 14:08:13 +0100 | |
---|---|---|
committer | 2023-02-02 14:08:13 +0100 | |
commit | 382512a5a6cc3f13576bbde8d607098d019f4063 (patch) | |
tree | dc2ccd1d30cd65b3f3d576a8d2a6910bbecc593a /internal/api/client/instance | |
parent | [chore/performance] use only 1 sqlite db connection regardless of multiplier ... (diff) | |
download | gotosocial-382512a5a6cc3f13576bbde8d607098d019f4063.tar.xz |
[feature] Implement `/api/v2/instance` endpoint (#1409)
* interim: start adding /api/v2/instance
* finish up
Diffstat (limited to 'internal/api/client/instance')
-rw-r--r-- | internal/api/client/instance/instance.go | 16 | ||||
-rw-r--r-- | internal/api/client/instance/instanceget.go | 48 | ||||
-rw-r--r-- | internal/api/client/instance/instancepatch.go | 12 | ||||
-rw-r--r-- | internal/api/client/instance/instancepatch_test.go | 49 | ||||
-rw-r--r-- | internal/api/client/instance/instancepeersget.go | 12 |
5 files changed, 97 insertions, 40 deletions
diff --git a/internal/api/client/instance/instance.go b/internal/api/client/instance/instance.go index fa6862e27..d6f54a1ed 100644 --- a/internal/api/client/instance/instance.go +++ b/internal/api/client/instance/instance.go @@ -26,12 +26,10 @@ import ( ) const ( - // InstanceInformationPath is for serving instance info requests, minus the 'api' prefix. - InstanceInformationPath = "/v1/instance" - // InstancePeersPath is for serving instance peers requests. - InstancePeersPath = InstanceInformationPath + "/peers" - // PeersFilterKey is used to provide filters to /api/v1/instance/peers - PeersFilterKey = "filter" + InstanceInformationPathV1 = "/v1/instance" + InstanceInformationPathV2 = "/v2/instance" + InstancePeersPath = InstanceInformationPathV1 + "/peers" + PeersFilterKey = "filter" // PeersFilterKey is used to provide filters to /api/v1/instance/peers ) type Module struct { @@ -45,7 +43,9 @@ func New(processor processing.Processor) *Module { } func (m *Module) Route(attachHandler func(method string, path string, f ...gin.HandlerFunc) gin.IRoutes) { - attachHandler(http.MethodGet, InstanceInformationPath, m.InstanceInformationGETHandler) - attachHandler(http.MethodPatch, InstanceInformationPath, m.InstanceUpdatePATCHHandler) + attachHandler(http.MethodGet, InstanceInformationPathV1, m.InstanceInformationGETHandlerV1) + attachHandler(http.MethodGet, InstanceInformationPathV2, m.InstanceInformationGETHandlerV2) + + attachHandler(http.MethodPatch, InstanceInformationPathV1, m.InstanceUpdatePATCHHandler) attachHandler(http.MethodGet, InstancePeersPath, m.InstancePeersGETHandler) } diff --git a/internal/api/client/instance/instanceget.go b/internal/api/client/instance/instanceget.go index 438085771..f3027b1d7 100644 --- a/internal/api/client/instance/instanceget.go +++ b/internal/api/client/instance/instanceget.go @@ -22,13 +22,12 @@ import ( "net/http" apiutil "github.com/superseriousbusiness/gotosocial/internal/api/util" - "github.com/superseriousbusiness/gotosocial/internal/config" "github.com/superseriousbusiness/gotosocial/internal/gtserror" "github.com/gin-gonic/gin" ) -// InstanceInformationGETHandler swagger:operation GET /api/v1/instance instanceGet +// InstanceInformationV1GETHandlerV1 swagger:operation GET /api/v1/instance instanceGetV1 // // View instance information. // @@ -43,20 +42,55 @@ import ( // '200': // description: "Instance information." // schema: -// "$ref": "#/definitions/instance" +// "$ref": "#/definitions/instanceV1" // '406': // description: not acceptable // '500': // description: internal error -func (m *Module) InstanceInformationGETHandler(c *gin.Context) { +func (m *Module) InstanceInformationGETHandlerV1(c *gin.Context) { if _, err := apiutil.NegotiateAccept(c, apiutil.JSONAcceptHeaders...); err != nil { - apiutil.ErrorHandler(c, gtserror.NewErrorNotAcceptable(err, err.Error()), m.processor.InstanceGet) + apiutil.ErrorHandler(c, gtserror.NewErrorNotAcceptable(err, err.Error()), m.processor.InstanceGetV1) return } - instance, errWithCode := m.processor.InstanceGet(c.Request.Context(), config.GetHost()) + instance, errWithCode := m.processor.InstanceGetV1(c.Request.Context()) if errWithCode != nil { - apiutil.ErrorHandler(c, errWithCode, m.processor.InstanceGet) + apiutil.ErrorHandler(c, errWithCode, m.processor.InstanceGetV1) + return + } + + c.JSON(http.StatusOK, instance) +} + +// InstanceInformationGETHandlerV2 swagger:operation GET /api/v2/instance instanceGetV2 +// +// View instance information. +// +// --- +// tags: +// - instance +// +// produces: +// - application/json +// +// responses: +// '200': +// description: "Instance information." +// schema: +// "$ref": "#/definitions/instanceV2" +// '406': +// description: not acceptable +// '500': +// description: internal error +func (m *Module) InstanceInformationGETHandlerV2(c *gin.Context) { + if _, err := apiutil.NegotiateAccept(c, apiutil.JSONAcceptHeaders...); err != nil { + apiutil.ErrorHandler(c, gtserror.NewErrorNotAcceptable(err, err.Error()), m.processor.InstanceGetV1) + return + } + + instance, errWithCode := m.processor.InstanceGetV2(c.Request.Context()) + if errWithCode != nil { + apiutil.ErrorHandler(c, errWithCode, m.processor.InstanceGetV1) return } diff --git a/internal/api/client/instance/instancepatch.go b/internal/api/client/instance/instancepatch.go index 5fb691ac6..a71d670b9 100644 --- a/internal/api/client/instance/instancepatch.go +++ b/internal/api/client/instance/instancepatch.go @@ -130,35 +130,35 @@ import ( func (m *Module) InstanceUpdatePATCHHandler(c *gin.Context) { authed, err := oauth.Authed(c, true, true, true, true) if err != nil { - apiutil.ErrorHandler(c, gtserror.NewErrorUnauthorized(err, err.Error()), m.processor.InstanceGet) + apiutil.ErrorHandler(c, gtserror.NewErrorUnauthorized(err, err.Error()), m.processor.InstanceGetV1) return } if _, err := apiutil.NegotiateAccept(c, apiutil.JSONAcceptHeaders...); err != nil { - apiutil.ErrorHandler(c, gtserror.NewErrorNotAcceptable(err, err.Error()), m.processor.InstanceGet) + apiutil.ErrorHandler(c, gtserror.NewErrorNotAcceptable(err, err.Error()), m.processor.InstanceGetV1) return } if !*authed.User.Admin { err := errors.New("user is not an admin so cannot update instance settings") - apiutil.ErrorHandler(c, gtserror.NewErrorForbidden(err, err.Error()), m.processor.InstanceGet) + apiutil.ErrorHandler(c, gtserror.NewErrorForbidden(err, err.Error()), m.processor.InstanceGetV1) return } form := &apimodel.InstanceSettingsUpdateRequest{} if err := c.ShouldBind(&form); err != nil { - apiutil.ErrorHandler(c, gtserror.NewErrorBadRequest(err, err.Error()), m.processor.InstanceGet) + apiutil.ErrorHandler(c, gtserror.NewErrorBadRequest(err, err.Error()), m.processor.InstanceGetV1) return } if err := validateInstanceUpdate(form); err != nil { - apiutil.ErrorHandler(c, gtserror.NewErrorBadRequest(err, err.Error()), m.processor.InstanceGet) + apiutil.ErrorHandler(c, gtserror.NewErrorBadRequest(err, err.Error()), m.processor.InstanceGetV1) return } i, errWithCode := m.processor.InstancePatch(c.Request.Context(), form) if errWithCode != nil { - apiutil.ErrorHandler(c, errWithCode, m.processor.InstanceGet) + apiutil.ErrorHandler(c, errWithCode, m.processor.InstanceGetV1) return } diff --git a/internal/api/client/instance/instancepatch_test.go b/internal/api/client/instance/instancepatch_test.go index 0c209c78c..0b438b823 100644 --- a/internal/api/client/instance/instancepatch_test.go +++ b/internal/api/client/instance/instancepatch_test.go @@ -52,7 +52,7 @@ func (suite *InstancePatchTestSuite) TestInstancePatch1() { // set up the request recorder := httptest.NewRecorder() - ctx := suite.newContext(recorder, http.MethodPatch, instance.InstanceInformationPath, bodyBytes, w.FormDataContentType(), true) + ctx := suite.newContext(recorder, http.MethodPatch, instance.InstanceInformationPathV1, bodyBytes, w.FormDataContentType(), true) // call the handler suite.instanceModule.InstanceUpdatePATCHHandler(ctx) @@ -106,7 +106,8 @@ func (suite *InstancePatchTestSuite) TestInstancePatch1() { "max_expiration": 2629746 }, "accounts": { - "allow_custom_css": true + "allow_custom_css": true, + "max_featured_tags": 10 }, "emojis": { "emoji_size_limit": 51200 @@ -161,7 +162,7 @@ func (suite *InstancePatchTestSuite) TestInstancePatch2() { // set up the request recorder := httptest.NewRecorder() - ctx := suite.newContext(recorder, http.MethodPatch, instance.InstanceInformationPath, bodyBytes, w.FormDataContentType(), true) + ctx := suite.newContext(recorder, http.MethodPatch, instance.InstanceInformationPathV1, bodyBytes, w.FormDataContentType(), true) // call the handler suite.instanceModule.InstanceUpdatePATCHHandler(ctx) @@ -215,7 +216,8 @@ func (suite *InstancePatchTestSuite) TestInstancePatch2() { "max_expiration": 2629746 }, "accounts": { - "allow_custom_css": true + "allow_custom_css": true, + "max_featured_tags": 10 }, "emojis": { "emoji_size_limit": 51200 @@ -270,7 +272,7 @@ func (suite *InstancePatchTestSuite) TestInstancePatch3() { // set up the request recorder := httptest.NewRecorder() - ctx := suite.newContext(recorder, http.MethodPatch, instance.InstanceInformationPath, bodyBytes, w.FormDataContentType(), true) + ctx := suite.newContext(recorder, http.MethodPatch, instance.InstanceInformationPathV1, bodyBytes, w.FormDataContentType(), true) // call the handler suite.instanceModule.InstanceUpdatePATCHHandler(ctx) @@ -324,7 +326,8 @@ func (suite *InstancePatchTestSuite) TestInstancePatch3() { "max_expiration": 2629746 }, "accounts": { - "allow_custom_css": true + "allow_custom_css": true, + "max_featured_tags": 10 }, "emojis": { "emoji_size_limit": 51200 @@ -377,7 +380,7 @@ func (suite *InstancePatchTestSuite) TestInstancePatch4() { // set up the request recorder := httptest.NewRecorder() - ctx := suite.newContext(recorder, http.MethodPatch, instance.InstanceInformationPath, bodyBytes, w.FormDataContentType(), true) + ctx := suite.newContext(recorder, http.MethodPatch, instance.InstanceInformationPathV1, bodyBytes, w.FormDataContentType(), true) // call the handler suite.instanceModule.InstanceUpdatePATCHHandler(ctx) @@ -406,7 +409,7 @@ func (suite *InstancePatchTestSuite) TestInstancePatch5() { // set up the request recorder := httptest.NewRecorder() - ctx := suite.newContext(recorder, http.MethodPatch, instance.InstanceInformationPath, bodyBytes, w.FormDataContentType(), true) + ctx := suite.newContext(recorder, http.MethodPatch, instance.InstanceInformationPathV1, bodyBytes, w.FormDataContentType(), true) ctx.Set(oauth.SessionAuthorizedAccount, suite.testAccounts["local_account_1"]) ctx.Set(oauth.SessionAuthorizedToken, oauth.DBTokenToToken(suite.testTokens["local_account_1"])) @@ -440,7 +443,7 @@ func (suite *InstancePatchTestSuite) TestInstancePatch6() { // set up the request recorder := httptest.NewRecorder() - ctx := suite.newContext(recorder, http.MethodPatch, instance.InstanceInformationPath, bodyBytes, w.FormDataContentType(), true) + ctx := suite.newContext(recorder, http.MethodPatch, instance.InstanceInformationPathV1, bodyBytes, w.FormDataContentType(), true) // call the handler suite.instanceModule.InstanceUpdatePATCHHandler(ctx) @@ -494,7 +497,8 @@ func (suite *InstancePatchTestSuite) TestInstancePatch6() { "max_expiration": 2629746 }, "accounts": { - "allow_custom_css": true + "allow_custom_css": true, + "max_featured_tags": 10 }, "emojis": { "emoji_size_limit": 51200 @@ -549,7 +553,7 @@ func (suite *InstancePatchTestSuite) TestInstancePatch7() { // set up the request recorder := httptest.NewRecorder() - ctx := suite.newContext(recorder, http.MethodPatch, instance.InstanceInformationPath, bodyBytes, w.FormDataContentType(), true) + ctx := suite.newContext(recorder, http.MethodPatch, instance.InstanceInformationPathV1, bodyBytes, w.FormDataContentType(), true) // call the handler suite.instanceModule.InstanceUpdatePATCHHandler(ctx) @@ -578,7 +582,7 @@ func (suite *InstancePatchTestSuite) TestInstancePatch8() { // set up the request recorder := httptest.NewRecorder() - ctx := suite.newContext(recorder, http.MethodPatch, instance.InstanceInformationPath, bodyBytes, w.FormDataContentType(), true) + ctx := suite.newContext(recorder, http.MethodPatch, instance.InstanceInformationPathV1, bodyBytes, w.FormDataContentType(), true) // call the handler suite.instanceModule.InstanceUpdatePATCHHandler(ctx) @@ -636,7 +640,8 @@ func (suite *InstancePatchTestSuite) TestInstancePatch8() { "max_expiration": 2629746 }, "accounts": { - "allow_custom_css": true + "allow_custom_css": true, + "max_featured_tags": 10 }, "emojis": { "emoji_size_limit": 51200 @@ -678,6 +683,24 @@ func (suite *InstancePatchTestSuite) TestInstancePatch8() { }, "max_toot_chars": 5000 }`, dst.String()) + + // extra bonus: check the v2 model thumbnail after the patch + instanceV2, err := suite.processor.InstanceGetV2(ctx) + if err != nil { + suite.FailNow(err.Error()) + } + + instanceV2ThumbnailJson, err := json.MarshalIndent(instanceV2.Thumbnail, "", " ") + if err != nil { + suite.FailNow(err.Error()) + } + + suite.Equal(`{ + "url": "http://localhost:8080/fileserver/01AY6P665V14JJR0AFVRT7311Y/attachment/original/`+instanceAccount.AvatarMediaAttachment.ID+`.gif",`+` + "thumbnail_type": "image/gif", + "thumbnail_description": "A bouncing little green peglin.", + "blurhash": "LG9t;qRS4YtO.4WDRlt5IXoxtPj[" +}`, string(instanceV2ThumbnailJson)) } func TestInstancePatchTestSuite(t *testing.T) { diff --git a/internal/api/client/instance/instancepeersget.go b/internal/api/client/instance/instancepeersget.go index 9e2ed89e5..ab1f8d28d 100644 --- a/internal/api/client/instance/instancepeersget.go +++ b/internal/api/client/instance/instancepeersget.go @@ -102,14 +102,14 @@ import ( func (m *Module) InstancePeersGETHandler(c *gin.Context) { authed, err := oauth.Authed(c, false, false, false, false) if err != nil { - apiutil.ErrorHandler(c, gtserror.NewErrorUnauthorized(err, err.Error()), m.processor.InstanceGet) + apiutil.ErrorHandler(c, gtserror.NewErrorUnauthorized(err, err.Error()), m.processor.InstanceGetV1) return } var isUnauthenticated = authed.Account == nil || authed.User == nil if _, err := apiutil.NegotiateAccept(c, apiutil.JSONAcceptHeaders...); err != nil { - apiutil.ErrorHandler(c, gtserror.NewErrorNotAcceptable(err, err.Error()), m.processor.InstanceGet) + apiutil.ErrorHandler(c, gtserror.NewErrorNotAcceptable(err, err.Error()), m.processor.InstanceGetV1) return } @@ -127,7 +127,7 @@ func (m *Module) InstancePeersGETHandler(c *gin.Context) { includeOpen = true default: err := fmt.Errorf("filter %s not recognized; accepted values are 'open', 'suspended'", trimmed) - apiutil.ErrorHandler(c, gtserror.NewErrorBadRequest(err, err.Error()), m.processor.InstanceGet) + apiutil.ErrorHandler(c, gtserror.NewErrorBadRequest(err, err.Error()), m.processor.InstanceGetV1) return } } @@ -141,19 +141,19 @@ func (m *Module) InstancePeersGETHandler(c *gin.Context) { if includeOpen && !config.GetInstanceExposePeers() && isUnauthenticated { err := fmt.Errorf("peers open query requires an authenticated account/user") - apiutil.ErrorHandler(c, gtserror.NewErrorUnauthorized(err, err.Error()), m.processor.InstanceGet) + apiutil.ErrorHandler(c, gtserror.NewErrorUnauthorized(err, err.Error()), m.processor.InstanceGetV1) return } if includeSuspended && !config.GetInstanceExposeSuspended() && isUnauthenticated { err := fmt.Errorf("peers suspended query requires an authenticated account/user") - apiutil.ErrorHandler(c, gtserror.NewErrorUnauthorized(err, err.Error()), m.processor.InstanceGet) + apiutil.ErrorHandler(c, gtserror.NewErrorUnauthorized(err, err.Error()), m.processor.InstanceGetV1) return } data, errWithCode := m.processor.InstancePeersGet(c.Request.Context(), includeSuspended, includeOpen, flat) if errWithCode != nil { - apiutil.ErrorHandler(c, errWithCode, m.processor.InstanceGet) + apiutil.ErrorHandler(c, errWithCode, m.processor.InstanceGetV1) return } |