And follow requests work!

Who knew that Mastodon would set the accept target's object id to the
internal one?

But also, I am of the opinion that this is a bug on our side when
translating the activity to AP
This commit is contained in:
Melody Becker 2025-06-12 17:13:19 +02:00
parent 3c141e21fd
commit 9e23f82e55
Signed by: mstar
SSH key fingerprint: SHA256:9VAo09aaVNTWKzPW7Hq2LW+ox9OdwmTSHRoD4mlz1yI

View file

@ -387,6 +387,7 @@ func handleAccept(w http.ResponseWriter, r *http.Request, object map[string]any)
log := hlog.FromRequest(r) log := hlog.FromRequest(r)
rawTarget, ok := object["object"] rawTarget, ok := object["object"]
if !ok { if !ok {
log.Debug().Msg("Rejecting accept, missing object")
_ = webutils.ProblemDetails( _ = webutils.ProblemDetails(
w, w,
http.StatusBadRequest, http.StatusBadRequest,
@ -397,7 +398,6 @@ func handleAccept(w http.ResponseWriter, r *http.Request, object map[string]any)
) )
return true return true
} }
// FIXME: Also handle other undo cases, such as follows
var targetObjectId string var targetObjectId string
// I *think* the spec says that this must be an object. Not sure though // I *think* the spec says that this must be an object. Not sure though
switch target := rawTarget.(type) { switch target := rawTarget.(type) {
@ -406,7 +406,20 @@ func handleAccept(w http.ResponseWriter, r *http.Request, object map[string]any)
case map[string]any: case map[string]any:
objType, ok := target["type"].(string) objType, ok := target["type"].(string)
// TODO: Ensure accept is only used for follows // TODO: Ensure accept is only used for follows
if !ok || objType != "Follow" { if !ok {
log.Debug().Msg("Rejecting accept, missing embedded object data")
_ = webutils.ProblemDetails(
w,
http.StatusBadRequest,
"/errors/bad-request-data",
"Bad activity data",
other.IntoPointer(`Target object must contain a type field`),
nil,
)
return true
}
if objType != "Follow" {
log.Debug().Msg("Rejecting accept, bad object type")
_ = webutils.ProblemDetails( _ = webutils.ProblemDetails(
w, w,
http.StatusBadRequest, http.StatusBadRequest,
@ -419,6 +432,7 @@ func handleAccept(w http.ResponseWriter, r *http.Request, object map[string]any)
} }
targetObjectId, ok = target["id"].(string) targetObjectId, ok = target["id"].(string)
if !ok { if !ok {
log.Debug().Msg("Rejecting accept, missing object id")
_ = webutils.ProblemDetails( _ = webutils.ProblemDetails(
w, w,
http.StatusBadRequest, http.StatusBadRequest,
@ -430,6 +444,7 @@ func handleAccept(w http.ResponseWriter, r *http.Request, object map[string]any)
return true return true
} }
default: default:
log.Debug().Msg("Rejecting accept, missing object field")
_ = webutils.ProblemDetails( _ = webutils.ProblemDetails(
w, w,
http.StatusBadRequest, http.StatusBadRequest,
@ -440,22 +455,29 @@ func handleAccept(w http.ResponseWriter, r *http.Request, object map[string]any)
) )
return true return true
} }
internalIdMatch := objectIdRegex.FindStringSubmatch(targetObjectId) var internalId string
if len(internalIdMatch) != 2 { if strings.HasPrefix(targetObjectId, "http") {
_ = webutils.ProblemDetails( internalIdMatch := objectIdRegex.FindStringSubmatch(targetObjectId)
w, if len(internalIdMatch) != 2 {
http.StatusBadRequest, log.Debug().Msg("Rejecting accept, objectIdRegex didn't match")
"/errors/bad-request-data", _ = webutils.ProblemDetails(
"Bad activity data", w,
other.IntoPointer(`Request data target object is not internal id`), http.StatusBadRequest,
nil, "/errors/bad-request-data",
) "Bad activity data",
return true other.IntoPointer(`Request data target object is not internal id`),
nil,
)
return true
}
internalId = internalIdMatch[1]
} else {
internalId = targetObjectId
} }
internalId := internalIdMatch[1]
followActivity, err := dbgen.Activity.Where(dbgen.Activity.Id.Eq(internalId)).First() followActivity, err := dbgen.Activity.Where(dbgen.Activity.Id.Eq(internalId)).First()
switch err { switch err {
case gorm.ErrRecordNotFound: case gorm.ErrRecordNotFound:
log.Debug().Msg("Rejecting accept, target follow activity not found")
_ = webutils.ProblemDetailsStatusOnly(w, http.StatusNotFound) _ = webutils.ProblemDetailsStatusOnly(w, http.StatusNotFound)
return true return true
case nil: case nil: