Work on Accept activity

This commit is contained in:
Melody Becker 2025-05-09 19:18:26 +02:00
parent e1051e81ac
commit b0e344b170
3 changed files with 209 additions and 0 deletions

View file

@ -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) {}