summaryrefslogtreecommitdiff
path: root/internal/web/thread.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/web/thread.go')
-rw-r--r--internal/web/thread.go96
1 files changed, 73 insertions, 23 deletions
diff --git a/internal/web/thread.go b/internal/web/thread.go
index 3a9839281..5e953ee06 100644
--- a/internal/web/thread.go
+++ b/internal/web/thread.go
@@ -19,65 +19,88 @@
package web
import (
+ "context"
+ "encoding/json"
+ "errors"
+ "fmt"
"net/http"
"strings"
- "github.com/sirupsen/logrus"
-
"github.com/gin-gonic/gin"
+ "github.com/superseriousbusiness/gotosocial/internal/ap"
+ "github.com/superseriousbusiness/gotosocial/internal/api"
+ apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
"github.com/superseriousbusiness/gotosocial/internal/config"
+ "github.com/superseriousbusiness/gotosocial/internal/gtserror"
"github.com/superseriousbusiness/gotosocial/internal/oauth"
)
-func (m *Module) threadTemplateHandler(c *gin.Context) {
- l := logrus.WithField("func", "threadTemplateGET")
- l.Trace("rendering thread template")
-
+func (m *Module) threadGETHandler(c *gin.Context) {
ctx := c.Request.Context()
+ authed, err := oauth.Authed(c, false, false, false, false)
+ if err != nil {
+ api.ErrorHandler(c, gtserror.NewErrorUnauthorized(err, err.Error()), m.processor.InstanceGet)
+ return
+ }
+
// usernames on our instance will always be lowercase
username := strings.ToLower(c.Param(usernameKey))
if username == "" {
- c.JSON(http.StatusBadRequest, gin.H{"error": "no account username specified"})
+ err := errors.New("no account username specified")
+ api.ErrorHandler(c, gtserror.NewErrorBadRequest(err, err.Error()), m.processor.InstanceGet)
return
}
// status ids will always be uppercase
statusID := strings.ToUpper(c.Param(statusIDKey))
if statusID == "" {
- c.JSON(http.StatusBadRequest, gin.H{"error": "no status id specified"})
+ err := errors.New("no status id specified")
+ api.ErrorHandler(c, gtserror.NewErrorBadRequest(err, err.Error()), m.processor.InstanceGet)
return
}
- authed, err := oauth.Authed(c, false, false, false, false)
+ host := config.GetHost()
+ instance, err := m.processor.InstanceGet(ctx, host)
if err != nil {
- l.Errorf("error authing status GET request: %s", err)
- c.JSON(http.StatusBadRequest, gin.H{"error": "status not found"})
+ api.ErrorHandler(c, gtserror.NewErrorInternalError(err), m.processor.InstanceGet)
return
}
- host := config.GetHost()
- instance, err := m.processor.InstanceGet(ctx, host)
- if err != nil {
- l.Debugf("error getting instance from processor: %s", err)
- c.JSON(http.StatusInternalServerError, gin.H{"error": "internal server error"})
+ instanceGet := func(ctx context.Context, domain string) (*apimodel.Instance, gtserror.WithCode) {
+ return instance, nil
+ }
+
+ // do this check to make sure the status is actually from a local account,
+ // we shouldn't render threads from statuses that don't belong to us!
+ if _, errWithCode := m.processor.AccountGetLocalByUsername(ctx, authed, username); errWithCode != nil {
+ api.ErrorHandler(c, errWithCode, instanceGet)
return
}
- status, err := m.processor.StatusGet(ctx, authed, statusID)
- if err != nil {
- c.JSON(http.StatusBadRequest, gin.H{"error": "status not found"})
+ status, errWithCode := m.processor.StatusGet(ctx, authed, statusID)
+ if errWithCode != nil {
+ api.ErrorHandler(c, errWithCode, instanceGet)
return
}
if !strings.EqualFold(username, status.Account.Username) {
- c.JSON(http.StatusBadRequest, gin.H{"error": "status not found"})
+ err := gtserror.NewErrorNotFound(errors.New("path username not equal to status author username"))
+ api.ErrorHandler(c, gtserror.NewErrorNotFound(err), instanceGet)
return
}
- context, err := m.processor.StatusGetContext(ctx, authed, statusID)
- if err != nil {
- c.JSON(http.StatusBadRequest, gin.H{"error": "status not found"})
+ // if we're getting an AP request on this endpoint we
+ // should render the status's AP representation instead
+ accept := c.NegotiateFormat(string(api.TextHTML), string(api.AppActivityJSON), string(api.AppActivityLDJSON))
+ if accept == string(api.AppActivityJSON) || accept == string(api.AppActivityLDJSON) {
+ m.returnAPStatus(ctx, c, username, statusID, accept)
+ return
+ }
+
+ context, errWithCode := m.processor.StatusGetContext(ctx, authed, statusID)
+ if errWithCode != nil {
+ api.ErrorHandler(c, errWithCode, instanceGet)
return
}
@@ -88,3 +111,30 @@ func (m *Module) threadTemplateHandler(c *gin.Context) {
"stylesheets": []string{"/assets/Fork-Awesome/css/fork-awesome.min.css", "/assets/status.css"},
})
}
+
+func (m *Module) returnAPStatus(ctx context.Context, c *gin.Context, username string, statusID string, accept string) {
+ verifier, signed := c.Get(string(ap.ContextRequestingPublicKeyVerifier))
+ if signed {
+ ctx = context.WithValue(ctx, ap.ContextRequestingPublicKeyVerifier, verifier)
+ }
+
+ signature, signed := c.Get(string(ap.ContextRequestingPublicKeySignature))
+ if signed {
+ ctx = context.WithValue(ctx, ap.ContextRequestingPublicKeySignature, signature)
+ }
+
+ status, errWithCode := m.processor.GetFediStatus(ctx, username, statusID, c.Request.URL)
+ if errWithCode != nil {
+ api.ErrorHandler(c, errWithCode, m.processor.InstanceGet)
+ return
+ }
+
+ b, mErr := json.Marshal(status)
+ if mErr != nil {
+ err := fmt.Errorf("could not marshal json: %s", mErr)
+ api.ErrorHandler(c, gtserror.NewErrorInternalError(err), m.processor.InstanceGet)
+ return
+ }
+
+ c.Data(http.StatusOK, accept, b)
+}