Add support for resolving Application actors and fix error handling with failed resolution. Fixes #1710

This commit is contained in:
Gabe Kangas 2022-01-30 11:44:17 -08:00
parent 7cd5b0cc94
commit 4e76fff0d0
No known key found for this signature in database
GPG key ID: 9A56337728BC81EA
2 changed files with 72 additions and 5 deletions

View file

@ -78,6 +78,25 @@ func MakeActorFromService(service vocab.ActivityStreamsService) ActivityPubActor
return apActor
}
// MakeActorFromApplication takes a full ActivityPub application and returns
// our internal representation of an actor.
func MakeActorFromApplication(application vocab.ActivityStreamsApplication) ActivityPubActor {
apActor := ActivityPubActor{
ActorIri: application.GetJSONLDId().Get(),
Inbox: application.GetActivityStreamsInbox().GetIRI(),
Name: application.GetActivityStreamsName().Begin().GetXMLSchemaString(),
Username: application.GetActivityStreamsPreferredUsername().GetXMLSchemaString(),
FullUsername: GetFullUsernameFromApplication(application),
W3IDSecurityV1PublicKey: application.GetW3IDSecurityV1PublicKey(),
}
if application.GetActivityStreamsIcon() != nil && application.GetActivityStreamsIcon().Len() > 0 && application.GetActivityStreamsIcon().At(0).GetActivityStreamsImage() != nil {
apActor.Image = application.GetActivityStreamsIcon().At(0).GetActivityStreamsImage().GetActivityStreamsUrl().Begin().GetIRI()
}
return apActor
}
// MakeActorPropertyWithID will return an actor property filled with the provided IRI.
func MakeActorPropertyWithID(idIRI *url.URL) vocab.ActivityStreamsActorProperty {
actor := streams.NewActivityStreamsActorProperty()
@ -238,6 +257,15 @@ func GetFullUsernameFromService(person vocab.ActivityStreamsService) string {
return fullUsername
}
// GetFullUsernameFromApplication will return the user@host.tld formatted user given a service object.
func GetFullUsernameFromApplication(person vocab.ActivityStreamsApplication) string {
hostname := person.GetJSONLDId().GetIRI().Hostname()
username := person.GetActivityStreamsPreferredUsername().GetXMLSchemaString()
fullUsername := fmt.Sprintf("%s@%s", username, hostname)
return fullUsername
}
func addMetadataLinkToProfile(profile vocab.ActivityStreamsService, name string, url string) {
attachments := profile.GetActivityStreamsAttachment()
if attachments == nil {

View file

@ -76,6 +76,7 @@ func ResolveIRI(c context.Context, iri string, callbacks ...interface{}) error {
func GetResolvedActorFromActorProperty(actor vocab.ActivityStreamsActorProperty) (apmodels.ActivityPubActor, error) {
var err error
var apActor apmodels.ActivityPubActor
resolved := false
personCallback := func(c context.Context, person vocab.ActivityStreamsPerson) error {
apActor = apmodels.MakeActorFromPerson(person)
@ -87,39 +88,77 @@ func GetResolvedActorFromActorProperty(actor vocab.ActivityStreamsActorProperty)
return nil
}
applicationCallback := func(c context.Context, s vocab.ActivityStreamsApplication) error {
apActor = apmodels.MakeActorFromApplication(s)
resolved = true
return nil
}
for iter := actor.Begin(); iter != actor.End(); iter = iter.Next() {
if iter.IsIRI() {
iri := iter.GetIRI()
if e := ResolveIRI(context.Background(), iri.String(), personCallback, serviceCallback); e != nil {
if e := ResolveIRI(context.Background(), iri.String(), personCallback, serviceCallback, applicationCallback); e != nil {
err = e
}
} else if iter.IsActivityStreamsPerson() {
person := iter.GetActivityStreamsPerson()
apActor = apmodels.MakeActorFromPerson(person)
resolved = true
} else if iter.IsActivityStreamsService() {
person := iter.GetActivityStreamsService()
apActor = apmodels.MakeActorFromService(person)
resolved = true
} else if iter.IsActivityStreamsApplication() {
person := iter.GetActivityStreamsApplication()
apActor = apmodels.MakeActorFromApplication(person)
resolved = true
}
}
return apActor, errors.Wrap(err, "unable to resolve actor from actor property")
if err != nil {
err = errors.Wrap(err, "error resolving actor from property value")
}
if !resolved {
err = errors.New("error resolving actor from property value")
}
return apActor, err
}
// GetResolvedActorFromIRI will resolve an IRI string to a fully populated actor.
func GetResolvedActorFromIRI(personOrServiceIRI string) (apmodels.ActivityPubActor, error) {
var err error
var apActor apmodels.ActivityPubActor
resolved := false
personCallback := func(c context.Context, person vocab.ActivityStreamsPerson) error {
apActor = apmodels.MakeActorFromPerson(person)
resolved = true
return nil
}
serviceCallback := func(c context.Context, s vocab.ActivityStreamsService) error {
apActor = apmodels.MakeActorFromService(s)
resolved = true
return nil
}
if e := ResolveIRI(context.Background(), personOrServiceIRI, personCallback, serviceCallback); e != nil {
applicationCallback := func(c context.Context, s vocab.ActivityStreamsApplication) error {
apActor = apmodels.MakeActorFromApplication(s)
resolved = true
return nil
}
if e := ResolveIRI(context.Background(), personOrServiceIRI, personCallback, serviceCallback, applicationCallback); e != nil {
err = e
}
return apActor, errors.Wrap(err, "unable to resolve actor from IRI string: "+personOrServiceIRI)
if err != nil {
err = errors.Wrap(err, "error resolving actor from property value")
}
if !resolved {
err = errors.New("error resolving actor from property value")
}
return apActor, err
}