resolve.go 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. package resolvers
  2. import (
  3. "context"
  4. "encoding/json"
  5. "io"
  6. "net/http"
  7. "github.com/go-fed/activity/streams"
  8. "github.com/go-fed/activity/streams/vocab"
  9. "github.com/owncast/owncast/activitypub/apmodels"
  10. "github.com/owncast/owncast/activitypub/crypto"
  11. "github.com/owncast/owncast/core/data"
  12. "github.com/pkg/errors"
  13. log "github.com/sirupsen/logrus"
  14. )
  15. // Resolve will translate a raw ActivityPub payload and fire the callback associated with that activity type.
  16. func Resolve(c context.Context, data []byte, callbacks ...interface{}) error {
  17. jsonResolver, err := streams.NewJSONResolver(callbacks...)
  18. if err != nil {
  19. // Something in the setup was wrong. For example, a callback has an
  20. // unsupported signature and would never be called
  21. return err
  22. }
  23. var jsonMap map[string]interface{}
  24. if err = json.Unmarshal(data, &jsonMap); err != nil {
  25. return err
  26. }
  27. log.Debugln("Resolving payload...", string(data))
  28. // The createCallback function will be called.
  29. err = jsonResolver.Resolve(c, jsonMap)
  30. if err != nil && !streams.IsUnmatchedErr(err) {
  31. // Something went wrong
  32. return err
  33. } else if streams.IsUnmatchedErr(err) {
  34. // Everything went right but the callback didn't match or the ActivityStreams
  35. // type is one that wasn't code generated.
  36. log.Debugln("No match: ", err)
  37. }
  38. return nil
  39. }
  40. // ResolveIRI will resolve an IRI ahd call the correct callback for the resolved type.
  41. func ResolveIRI(c context.Context, iri string, callbacks ...interface{}) error {
  42. log.Debugln("Resolving", iri)
  43. req, _ := http.NewRequest(http.MethodGet, iri, nil)
  44. actor := apmodels.MakeLocalIRIForAccount(data.GetDefaultFederationUsername())
  45. if err := crypto.SignRequest(req, nil, actor); err != nil {
  46. return err
  47. }
  48. response, err := http.DefaultClient.Do(req)
  49. if err != nil {
  50. return err
  51. }
  52. defer response.Body.Close()
  53. data, err := io.ReadAll(response.Body)
  54. if err != nil {
  55. return err
  56. }
  57. // fmt.Println(string(data))
  58. return Resolve(c, data, callbacks...)
  59. }
  60. // GetResolvedActorFromActorProperty resolve an external actor property to a
  61. // fully populated internal actor representation.
  62. func GetResolvedActorFromActorProperty(actor vocab.ActivityStreamsActorProperty) (apmodels.ActivityPubActor, error) {
  63. var err error
  64. var apActor apmodels.ActivityPubActor
  65. resolved := false
  66. if !actor.Empty() && actor.Len() > 0 && actor.At(0) != nil {
  67. // Explicitly use only the first actor that might be listed.
  68. actorObjectOrIRI := actor.At(0)
  69. var actorEntity apmodels.ExternalEntity
  70. // If the actor is an unresolved IRI then we need to resolve it.
  71. if actorObjectOrIRI.IsIRI() {
  72. iri := actorObjectOrIRI.GetIRI().String()
  73. return GetResolvedActorFromIRI(iri)
  74. }
  75. if actorObjectOrIRI.IsActivityStreamsPerson() {
  76. actorEntity = actorObjectOrIRI.GetActivityStreamsPerson()
  77. } else if actorObjectOrIRI.IsActivityStreamsService() {
  78. actorEntity = actorObjectOrIRI.GetActivityStreamsService()
  79. } else if actorObjectOrIRI.IsActivityStreamsApplication() {
  80. actorEntity = actorObjectOrIRI.GetActivityStreamsApplication()
  81. } else {
  82. err = errors.New("unrecognized external ActivityPub type: " + actorObjectOrIRI.Name())
  83. return apActor, err
  84. }
  85. // If any of the resolution or population failed then return the error.
  86. if err != nil {
  87. return apActor, err
  88. }
  89. // Convert the external AP entity into an internal actor representation.
  90. apa, e := apmodels.MakeActorFromExernalAPEntity(actorEntity)
  91. if apa != nil {
  92. apActor = *apa
  93. resolved = true
  94. }
  95. err = e
  96. }
  97. if !resolved && err == nil {
  98. err = errors.New("unknown error resolving actor from property value")
  99. }
  100. return apActor, err
  101. }
  102. // GetResolvedPublicKeyFromIRI will resolve a publicKey IRI string to a vocab.W3IDSecurityV1PublicKey.
  103. func GetResolvedPublicKeyFromIRI(publicKeyIRI string) (vocab.W3IDSecurityV1PublicKey, error) {
  104. var err error
  105. var pubkey vocab.W3IDSecurityV1PublicKey
  106. resolved := false
  107. personCallback := func(c context.Context, person vocab.ActivityStreamsPerson) error {
  108. if pkProp := person.GetW3IDSecurityV1PublicKey(); pkProp != nil {
  109. for iter := pkProp.Begin(); iter != pkProp.End(); iter = iter.Next() {
  110. if iter.IsW3IDSecurityV1PublicKey() {
  111. pubkey = iter.Get()
  112. resolved = true
  113. return nil
  114. }
  115. }
  116. }
  117. return errors.New("error deriving publickey from activitystreamsperson")
  118. }
  119. serviceCallback := func(c context.Context, service vocab.ActivityStreamsService) error {
  120. if pkProp := service.GetW3IDSecurityV1PublicKey(); pkProp != nil {
  121. for iter := pkProp.Begin(); iter != pkProp.End(); iter = iter.Next() {
  122. if iter.IsW3IDSecurityV1PublicKey() {
  123. pubkey = iter.Get()
  124. resolved = true
  125. return nil
  126. }
  127. }
  128. }
  129. return errors.New("error deriving publickey from activitystreamsservice")
  130. }
  131. applicationCallback := func(c context.Context, app vocab.ActivityStreamsApplication) error {
  132. if pkProp := app.GetW3IDSecurityV1PublicKey(); pkProp != nil {
  133. for iter := pkProp.Begin(); iter != pkProp.End(); iter = iter.Next() {
  134. if iter.IsW3IDSecurityV1PublicKey() {
  135. pubkey = iter.Get()
  136. resolved = true
  137. return nil
  138. }
  139. }
  140. }
  141. return errors.New("error deriving publickey from activitystreamsapp")
  142. }
  143. pubkeyCallback := func(c context.Context, pk vocab.W3IDSecurityV1PublicKey) error {
  144. pubkey = pk
  145. resolved = true
  146. return nil
  147. }
  148. if e := ResolveIRI(context.Background(), publicKeyIRI, personCallback, serviceCallback, applicationCallback, pubkeyCallback); e != nil {
  149. err = e
  150. }
  151. if err != nil {
  152. err = errors.Wrap(err, "error resolving publickey from iri, actor may not be valid: "+publicKeyIRI)
  153. }
  154. if !resolved {
  155. err = errors.New("error resolving publickey from iri, actor may not be valid: " + publicKeyIRI)
  156. }
  157. return pubkey, err
  158. }
  159. // GetResolvedActorFromIRI will resolve an IRI string to a fully populated actor.
  160. func GetResolvedActorFromIRI(personOrServiceIRI string) (apmodels.ActivityPubActor, error) {
  161. var err error
  162. var apActor apmodels.ActivityPubActor
  163. resolved := false
  164. personCallback := func(c context.Context, person vocab.ActivityStreamsPerson) error {
  165. apa, e := apmodels.MakeActorFromExernalAPEntity(person)
  166. if apa != nil {
  167. apActor = *apa
  168. resolved = true
  169. }
  170. return e
  171. }
  172. serviceCallback := func(c context.Context, service vocab.ActivityStreamsService) error {
  173. apa, e := apmodels.MakeActorFromExernalAPEntity(service)
  174. if apa != nil {
  175. apActor = *apa
  176. resolved = true
  177. }
  178. return e
  179. }
  180. applicationCallback := func(c context.Context, app vocab.ActivityStreamsApplication) error {
  181. apa, e := apmodels.MakeActorFromExernalAPEntity(app)
  182. if apa != nil {
  183. apActor = *apa
  184. resolved = true
  185. }
  186. return e
  187. }
  188. if e := ResolveIRI(context.Background(), personOrServiceIRI, personCallback, serviceCallback, applicationCallback); e != nil {
  189. err = e
  190. }
  191. if err != nil {
  192. err = errors.Wrap(err, "error resolving actor from property value")
  193. }
  194. if !resolved {
  195. err = errors.New("error resolving actor from property value")
  196. }
  197. return apActor, err
  198. }