Work on Accept activity
This commit is contained in:
parent
e1051e81ac
commit
b0e344b170
3 changed files with 209 additions and 0 deletions
56
samples/mkAcceptFollow.json
Normal file
56
samples/mkAcceptFollow.json
Normal file
|
@ -0,0 +1,56 @@
|
|||
{
|
||||
"@context": [
|
||||
"https://www.w3.org/ns/activitystreams",
|
||||
"https://w3id.org/security/v1",
|
||||
{
|
||||
"Key": "sec:Key",
|
||||
"manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
|
||||
"sensitive": "as:sensitive",
|
||||
"Hashtag": "as:Hashtag",
|
||||
"quoteUrl": "as:quoteUrl",
|
||||
"fedibird": "http://fedibird.com/ns#",
|
||||
"quoteUri": "fedibird:quoteUri",
|
||||
"toot": "http://joinmastodon.org/ns#",
|
||||
"Emoji": "toot:Emoji",
|
||||
"featured": "toot:featured",
|
||||
"discoverable": "toot:discoverable",
|
||||
"indexable": "toot:indexable",
|
||||
"schema": "http://schema.org#",
|
||||
"PropertyValue": "schema:PropertyValue",
|
||||
"value": "schema:value",
|
||||
"misskey": "https://misskey-hub.net/ns#",
|
||||
"_misskey_content": "misskey:_misskey_content",
|
||||
"_misskey_quote": "misskey:_misskey_quote",
|
||||
"_misskey_reaction": "misskey:_misskey_reaction",
|
||||
"_misskey_votes": "misskey:_misskey_votes",
|
||||
"_misskey_summary": "misskey:_misskey_summary",
|
||||
"_misskey_followedMessage": "misskey:_misskey_followedMessage",
|
||||
"_misskey_requireSigninToViewContents": "misskey:_misskey_requireSigninToViewContents",
|
||||
"_misskey_makeNotesFollowersOnlyBefore": "misskey:_misskey_makeNotesFollowersOnlyBefore",
|
||||
"_misskey_makeNotesHiddenBefore": "misskey:_misskey_makeNotesHiddenBefore",
|
||||
"_misskey_license": "misskey:_misskey_license",
|
||||
"freeText": {
|
||||
"@id": "misskey:freeText",
|
||||
"@type": "schema:text"
|
||||
},
|
||||
"isCat": "misskey:isCat",
|
||||
"firefish": "https://joinfirefish.org/ns#",
|
||||
"speakAsCat": "firefish:speakAsCat",
|
||||
"sharkey": "https://joinsharkey.org/ns#",
|
||||
"hideOnlineStatus": "sharkey:hideOnlineStatus",
|
||||
"backgroundUrl": "sharkey:backgroundUrl",
|
||||
"listenbrainz": "sharkey:listenbrainz",
|
||||
"enableRss": "sharkey:enableRss",
|
||||
"vcard": "http://www.w3.org/2006/vcard/ns#"
|
||||
}
|
||||
],
|
||||
"type": "Accept",
|
||||
"actor": "https://mk.absturztau.be/users/a1xy7910yc8401z8",
|
||||
"object": {
|
||||
"id": "https://activitypub.academy/b2574cea-3c77-4023-9f20-f3837f820aaf",
|
||||
"type": "Follow",
|
||||
"actor": "https://activitypub.academy/users/enulius_dorvorglan",
|
||||
"object": "https://mk.absturztau.be/users/a1xy7910yc8401z8"
|
||||
},
|
||||
"id": "https://mk.absturztau.be/5cfd9f47-2fdc-48cc-8fdd-0c8817811efc"
|
||||
}
|
56
samples/mkRejectRemoveFollow.json
Normal file
56
samples/mkRejectRemoveFollow.json
Normal file
|
@ -0,0 +1,56 @@
|
|||
{
|
||||
"@context": [
|
||||
"https://www.w3.org/ns/activitystreams",
|
||||
"https://w3id.org/security/v1",
|
||||
{
|
||||
"Key": "sec:Key",
|
||||
"manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
|
||||
"sensitive": "as:sensitive",
|
||||
"Hashtag": "as:Hashtag",
|
||||
"quoteUrl": "as:quoteUrl",
|
||||
"fedibird": "http://fedibird.com/ns#",
|
||||
"quoteUri": "fedibird:quoteUri",
|
||||
"toot": "http://joinmastodon.org/ns#",
|
||||
"Emoji": "toot:Emoji",
|
||||
"featured": "toot:featured",
|
||||
"discoverable": "toot:discoverable",
|
||||
"indexable": "toot:indexable",
|
||||
"schema": "http://schema.org#",
|
||||
"PropertyValue": "schema:PropertyValue",
|
||||
"value": "schema:value",
|
||||
"misskey": "https://misskey-hub.net/ns#",
|
||||
"_misskey_content": "misskey:_misskey_content",
|
||||
"_misskey_quote": "misskey:_misskey_quote",
|
||||
"_misskey_reaction": "misskey:_misskey_reaction",
|
||||
"_misskey_votes": "misskey:_misskey_votes",
|
||||
"_misskey_summary": "misskey:_misskey_summary",
|
||||
"_misskey_followedMessage": "misskey:_misskey_followedMessage",
|
||||
"_misskey_requireSigninToViewContents": "misskey:_misskey_requireSigninToViewContents",
|
||||
"_misskey_makeNotesFollowersOnlyBefore": "misskey:_misskey_makeNotesFollowersOnlyBefore",
|
||||
"_misskey_makeNotesHiddenBefore": "misskey:_misskey_makeNotesHiddenBefore",
|
||||
"_misskey_license": "misskey:_misskey_license",
|
||||
"freeText": {
|
||||
"@id": "misskey:freeText",
|
||||
"@type": "schema:text"
|
||||
},
|
||||
"isCat": "misskey:isCat",
|
||||
"firefish": "https://joinfirefish.org/ns#",
|
||||
"speakAsCat": "firefish:speakAsCat",
|
||||
"sharkey": "https://joinsharkey.org/ns#",
|
||||
"hideOnlineStatus": "sharkey:hideOnlineStatus",
|
||||
"backgroundUrl": "sharkey:backgroundUrl",
|
||||
"listenbrainz": "sharkey:listenbrainz",
|
||||
"enableRss": "sharkey:enableRss",
|
||||
"vcard": "http://www.w3.org/2006/vcard/ns#"
|
||||
}
|
||||
],
|
||||
"type": "Reject",
|
||||
"actor": "https://mk.absturztau.be/users/a1xy7910yc8401z8",
|
||||
"object": {
|
||||
"id": "https://mk.absturztau.be/follows/a7k4api7gap600n4/a1xy7910yc8401z8",
|
||||
"type": "Follow",
|
||||
"actor": "https://activitypub.academy/users/enulius_dorvorglan",
|
||||
"object": "https://mk.absturztau.be/users/a1xy7910yc8401z8"
|
||||
},
|
||||
"id": "https://mk.absturztau.be/779fd0e4-523c-4a67-a184-208f01f5d6f1"
|
||||
}
|
|
@ -7,6 +7,7 @@ import (
|
|||
"io"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strconv"
|
||||
|
||||
webutils "git.mstar.dev/mstar/goutils/http"
|
||||
"git.mstar.dev/mstar/goutils/other"
|
||||
|
@ -87,6 +88,10 @@ func userInbox(w http.ResponseWriter, r *http.Request) {
|
|||
handleUndo(w, r, data)
|
||||
case "Follow":
|
||||
handleFollow(w, r, data)
|
||||
case "Accept":
|
||||
handleAccept(w, r, data)
|
||||
case "Reject":
|
||||
handleReject(w, r, data)
|
||||
default:
|
||||
webutils.ProblemDetailsStatusOnly(w, 500)
|
||||
}
|
||||
|
@ -312,3 +317,95 @@ func handleFollow(w http.ResponseWriter, r *http.Request, object map[string]any)
|
|||
log.Error().Err(err).Msg("Failed to commit follow activity transaction")
|
||||
}
|
||||
}
|
||||
|
||||
func handleAccept(w http.ResponseWriter, r *http.Request, object map[string]any) {
|
||||
log := hlog.FromRequest(r)
|
||||
rawTarget, ok := object["object"]
|
||||
if !ok {
|
||||
webutils.ProblemDetails(
|
||||
w,
|
||||
http.StatusBadRequest,
|
||||
"/errors/bad-request-data",
|
||||
"Bad activity data",
|
||||
other.IntoPointer(`Request data needs to contain a field "object"`),
|
||||
nil,
|
||||
)
|
||||
return
|
||||
}
|
||||
// FIXME: Also handle other undo cases, such as follows
|
||||
var targetObjectId string
|
||||
// I *think* the spec says that this must be an object. Not sure though
|
||||
switch target := rawTarget.(type) {
|
||||
case string:
|
||||
targetObjectId = target
|
||||
case map[string]any:
|
||||
objType, ok := target["type"].(string)
|
||||
// TODO: Ensure accept is only used for follows
|
||||
if !ok || objType != "Follow" {
|
||||
webutils.ProblemDetails(
|
||||
w,
|
||||
http.StatusBadRequest,
|
||||
"/errors/bad-request-data",
|
||||
"Bad activity data",
|
||||
other.IntoPointer(`Target object type must be a string with value "Follow"`),
|
||||
nil,
|
||||
)
|
||||
return
|
||||
}
|
||||
targetObjectId, ok = target["id"].(string)
|
||||
if !ok {
|
||||
webutils.ProblemDetails(
|
||||
w,
|
||||
http.StatusBadRequest,
|
||||
"/errors/bad-request-data",
|
||||
"Bad activity data",
|
||||
other.IntoPointer(`Missing id in undone object`),
|
||||
nil,
|
||||
)
|
||||
return
|
||||
}
|
||||
default:
|
||||
webutils.ProblemDetails(
|
||||
w,
|
||||
http.StatusBadRequest,
|
||||
"/errors/bad-request-data",
|
||||
"Bad activity data",
|
||||
other.IntoPointer(`Request data needs to contain a field "object" of type string or object`),
|
||||
nil,
|
||||
)
|
||||
return
|
||||
}
|
||||
internalIdMatch := objectIdRegex.FindStringSubmatch(targetObjectId)
|
||||
if len(internalIdMatch) != 2 {
|
||||
webutils.ProblemDetails(
|
||||
w,
|
||||
http.StatusBadRequest,
|
||||
"/errors/bad-request-data",
|
||||
"Bad activity data",
|
||||
other.IntoPointer(`Request data target object is not internal id`),
|
||||
nil,
|
||||
)
|
||||
return
|
||||
}
|
||||
internalId := internalIdMatch[1]
|
||||
followActivity, err := dbgen.Activity.Where(dbgen.Activity.Id.Eq(internalId)).First()
|
||||
switch err {
|
||||
case gorm.ErrRecordNotFound:
|
||||
webutils.ProblemDetailsStatusOnly(w, http.StatusNotFound)
|
||||
return
|
||||
case nil:
|
||||
default:
|
||||
log.Error().
|
||||
Err(err).
|
||||
Str("target-id", internalId).
|
||||
Msg("Failed to get target follow activity from db")
|
||||
webutils.ProblemDetailsStatusOnly(w, http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
relationId := other.Must(strconv.ParseUint(followActivity.ObjectId, 10, 64))
|
||||
dbrel := dbgen.UserToUserRelation
|
||||
_, err = dbrel.Where(dbrel.ID.Eq(relationId)).
|
||||
UpdateColumn(dbrel.Relation, models.RelationFollow)
|
||||
}
|
||||
|
||||
func handleReject(w http.ResponseWriter, r *http.Request, object map[string]any) {}
|
||||
|
|
Loading…
Reference in a new issue